├── .drone.sec ├── .drone.yml ├── .gitignore ├── README.md ├── app ├── app.js ├── index.html ├── modules │ ├── artboard │ │ ├── controllers │ │ │ └── artboard.ctrl.js │ │ ├── directives │ │ │ ├── artboard.directive.js │ │ │ └── artboard.tpl.html │ │ ├── index.js │ │ └── styles │ │ │ └── artboard.scss │ ├── data │ │ ├── index.js │ │ └── services │ │ │ └── data.service.js │ ├── nav │ │ ├── controllers │ │ │ └── nav.ctrl.js │ │ ├── directives │ │ │ ├── nav.directive.js │ │ │ └── nav.tpl.html │ │ ├── index.js │ │ └── styles │ │ │ └── nav.scss │ ├── page │ │ ├── controllers │ │ │ └── page.ctrl.js │ │ ├── directives │ │ │ ├── page.directive.js │ │ │ └── page.tpl.html │ │ ├── index.js │ │ └── styles │ │ │ └── page.scss │ └── pages │ │ └── pages.tpl.html └── styles │ └── app.scss ├── cli.js ├── gulpfile.js ├── index.js └── tasks │ ├── browserSync.js │ ├── build.js │ ├── clean.js │ ├── default.js │ ├── fonts.js │ ├── generate-data.js │ ├── gh-pages.js │ ├── html.js │ ├── images.js │ ├── scss.js │ └── webpack.js ├── main.js ├── package.json ├── screens ├── generated.png ├── logo.png └── sketch.png ├── sketch └── social-app-ui-kit.sketch └── sketchtool ├── bin ├── sketchmigrate └── sketchtool └── share └── sketchtool └── resources.bundle └── Contents ├── Info.plist └── Resources ├── RELEASE NOTES.txt ├── en.lproj └── InfoPlist.strings ├── noise-1.png ├── noise-2.png ├── noise-3.png └── noise-4.png /.drone.sec: -------------------------------------------------------------------------------- 1 | eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkExMjhHQ00ifQ.nVgwhtkljc6KZO19JGTtKHVqkzNVBku1aqoHW9ZGPNSZV4QG2AgZS2g8rH8CSQFtwZ8FybwqcjKeaBqnAbcCT00WFMFldlvgDnNLPF1YxEZIrmk9iDKZc12Ns3F70rCupddFQgOUUYjIxqseIvCEs_vooQeg_k4FB9MookRewqDncyTxMe7vThIZKHPSC6IoF0j9VqA79GOkoFWPD477kS89Sgk8tKrWrH4PQev8rXjTS6iIUsJkjqEKlYMOK40FGWwC4C2L1g31_um3dSzHouQb_HBJhEpU7UyT_Z2AI1Hb8rdXC5F8F23yl46VTNmrRzBOSkrUtn_VjZeIGLLzqQ.M6dumvYHz51Nx8Kb.zaMfkJwXLqkYyTs6UWhcsMgTTDZUBOPfuYdcFzh2pMUAmBKMvgQZeDKuPg8-8o7QCrhoSdflhvMwGBQOYFGKZxQxPHpDg621UFaDRik3MD2w7NtrO-ljM43pNYPBY--SUJVxYicimnRYrqZeY7wiDQt2pFR0TS8W3s94G-AWgJqMVyBGHzWNUgqWZw-rek-Srx9ZliVz_-Qebk5_XFSFFk8WTUFRsdZnEr7VgqDO3-FjtYtvYKI-AGJyasEegUxUvtyb30FnXgRbTmmNgZCbnmb3IsWmJJosUXcFP2uY3yDk_wH-h8uNwzfkR87Z0bcyv4zPj5gvAg2oBqeN39D62-eLFMiEB99tno_LZha7n3eOQZyzgBiLsncWWhspjsbwnywu39oGWU4YH5BEIP8whz-4njdHoZz9V1zanOoq3oauO-BXZX6ZKUdizPJCknjL9amEHeW2xMqrE1x4c9fjqn0skA.z6b8_clJi-A4SJchHMD2aA -------------------------------------------------------------------------------- /.drone.yml: -------------------------------------------------------------------------------- 1 | 2 | build: 3 | compile: 4 | image: node:6.3.1 5 | pull: true 6 | commands: 7 | - npm update 8 | 9 | 10 | publish: 11 | npm: 12 | username: $$NPM_USERNAME 13 | password: $$NPM_PASSWORD 14 | email: $$NPM_EMAIL 15 | registry: $$NPM_REGISTRY 16 | always_auth: $$NPM_ALWAYS_AUTH 17 | when: 18 | branch: master 19 | 20 | 21 | cache: 22 | mount: 23 | - node_modules -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | 39 | public/ 40 | 41 | pngs/ 42 | 43 | _artboards/ 44 | 45 | export/ 46 | 47 | *.sketch 48 | 49 | .publish -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Node Version](https://img.shields.io/node/v/sketch-preview.svg)](https://www.npmjs.com/package/sketch-preview) [![NPM Version](https://img.shields.io/npm/v/sketch-preview.svg)](https://www.npmjs.com/package/sketch-preview) [![NPM License](https://img.shields.io/npm/l/sketch-preview.svg)](https://www.npmjs.com/package/sketch-preview) 2 | 3 | [![Build Status](https://drone.stackdot.com/api/badges/stackdot/sketch-preview/status.svg)](https://drone.stackdot.com/stackdot/sketch-preview) [![dependencies Status](https://img.shields.io/david/stackdot/sketch-preview.svg)](https://david-dm.org/stackdot/sketch-preview) [![Code Climate](https://codeclimate.com/github/stackdot/sketch-preview/badges/gpa.svg)](https://codeclimate.com/github/stackdot/sketch-preview) [![downloads monthly](https://img.shields.io/npm/dm/sketch-preview.svg)](https://www.npmjs.com/package/sketch-preview) 4 | 5 | 6 | ![alt text](screens/logo.png "Sketch Preview") 7 | === 8 | 9 | Sketch UI Generator 10 | 11 | [Live GitHub Pages Demo](https://stackdot.github.io/sketch-preview/#/pages/4648C1B2-BFC9-40DE-A196-BBEF0C2E3165) 12 | 13 | Generates a Interactable HTML website with your Sketch file. 14 | 15 | ## Generated in Browser: 16 | ![alt text](screens/generated.png "Generated Preview") 17 | 18 | ## Actual Sketch App 19 | ![alt text](screens/sketch.png "Sketch App") 20 | 21 | 22 | Sketch file credits: [Sketch File](http://www.sketchappsources.com/free-source/1985-social-app-sketch-freebie-resource.html) 23 | 24 | 25 | 26 | 27 | 28 | 29 | Requirements: 30 | --- 31 | 32 | - Must be on Mac OSX ( You do *not* need Sketch App installed ) 33 | - [NodeJS](https://nodejs.org/en/download/) ( Version 6+ ) 34 | - We recommend using [Node Version Manager](https://github.com/creationix/nvm) 35 | 36 | 37 | 38 | 39 | 40 | 41 | To Get Started: 42 | --- 43 | 44 | Install the package: 45 | 46 | npm install sketch-preview -g 47 | 48 | Now you have a cli tool available, to use it: 49 | 50 | sketch-preview --input=mysketchfile.sketch --open 51 | 52 | The `--open` at the end tells sketch-preview to open a browser tab to view your generated site. Otherwise it will simply build the static site in the `public` directory. 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | Including in your Gulp 61 | --- 62 | 63 | You can also include this library in your gulp process, firstly make sure you install the package: 64 | 65 | npm install sketch-preview --save 66 | 67 | Then inside of your gulpfile.js: 68 | 69 | ```javascript 70 | // You must pass in your gulp variable for us to extend: 71 | const preview = require('sketch-preview')({ 72 | input: './sketch/TST.sketch', 73 | }, gulp) 74 | 75 | // Generate sketch preview files: 76 | gulp.task('export', preview) 77 | ``` 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | Running Dev: 86 | --- 87 | 88 | Inside the directory run: 89 | 90 | ```bash 91 | gulp 92 | ``` 93 | 94 | Be sure to run `npm update` to ensure all the NPM dependencies are up to date. 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | License 103 | ---- 104 | 105 | [MIT License](http://en.wikipedia.org/wiki/MIT_License) 106 | 107 | -------------------------------------------------------------------------------- /app/app.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | 4 | // 3rd party modules: 5 | const angular = require('angular') 6 | const lodash = require('lodash') 7 | const router = require('angular-ui-router') 8 | require('angular-animate') 9 | require('angular-aria') 10 | require('angular-panhandler') 11 | require('angular-material/angular-material') 12 | 13 | const pagesTpl = require('modules/pages/pages.tpl.html') 14 | 15 | // Local modules: 16 | require('modules/data') 17 | require('modules/nav') 18 | require('modules/page') 19 | require('modules/artboard') 20 | 21 | const $ = require('jquery') 22 | 23 | // Create App: 24 | angular.module('app', [ 25 | 'ui.router', 26 | 'app.data', 27 | 'app.page', 28 | 'app.nav', 29 | 'app.artboard', 30 | 'ngMaterial' 31 | ]).config(['$stateProvider', '$urlRouterProvider', '$mdThemingProvider', function( $stateProvider, $urlRouterProvider, $mdThemingProvider ){ 32 | 33 | // Theming 34 | $mdThemingProvider.theme('header') 35 | .primaryPalette('grey') 36 | .dark() 37 | 38 | // URL Routing: 39 | $urlRouterProvider.otherwise('/pages') 40 | $stateProvider 41 | .state('pages', { 42 | url: '/pages', 43 | views: { 44 | nav: { 45 | template: '' 46 | }, 47 | content: { 48 | template: pagesTpl 49 | } 50 | } 51 | }) 52 | .state('pages.page', { 53 | url: '/:id', 54 | views: { 55 | page: { 56 | template: '', 57 | controller: ['$scope', '$stateParams', function( $scope, $stateParams ){ 58 | // console.log('Pages page') 59 | $scope.pageId = $stateParams.id 60 | }] 61 | } 62 | } 63 | }) 64 | .state('pages.page.artboard', { 65 | url: '/:artboard', 66 | views: { 67 | 'page@pages': { 68 | template: '', 69 | controller: ['$scope', '$stateParams', function( $scope, $stateParams ){ 70 | console.log('Artboard') 71 | $scope.pageId = $stateParams.id 72 | $scope.artboardId = $stateParams.artboard 73 | }] 74 | } 75 | } 76 | }) 77 | 78 | 79 | }]) 80 | .controller('app.main', ['$scope', '$state', '$rootScope', 'dataService', function( $scope, $state, $rootScope, dataService ){ 81 | 82 | $scope.data = dataService.data 83 | if($scope.data.returned) redirectIfNoCurrentPage() 84 | $scope.$watch('data.returned', function(){ 85 | if(lodash.isEmpty( $scope.data.pages ) ) return false 86 | redirectIfNoCurrentPage() 87 | }) 88 | 89 | function redirectIfNoCurrentPage(){ 90 | if( lodash.isEmpty( lodash.get( $state, 'current.params.id', null ) ) ){ 91 | $state.go('pages.page', { id: $scope.data.pages[0].id }) 92 | $scope.data.updateCurrentPage() 93 | } 94 | } 95 | 96 | 97 | $(window).keydown(function(e){ 98 | if(e.metaKey && ( e.keyCode == 187 || e.keyCode == 189 )){ 99 | e.preventDefault() 100 | let direction = 'in' 101 | if( e.keyCode == 189 ) 102 | direction = 'out' 103 | $rootScope.$emit('zoom', { direction: direction, event: e }) 104 | } 105 | }) 106 | 107 | }]) 108 | 109 | -------------------------------------------------------------------------------- /app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Sketch Preview 4 | 5 | 6 | 7 | 8 |
9 |
Not Working..
10 |
11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/modules/artboard/controllers/artboard.ctrl.js: -------------------------------------------------------------------------------- 1 | // artboard controller: 2 | 3 | const lodash = require('lodash') 4 | 5 | module.exports = ( $scope, dataService ) => { 6 | 7 | // var self = this 8 | 9 | // $scope.page = {} 10 | // $scope.artboard = {} 11 | 12 | // dataService.get().then(( res ) => { 13 | // 14 | // console.log('D', $scope.page) 15 | // 16 | // }) 17 | 18 | $scope.data = {} 19 | $scope.data = dataService.data 20 | $scope.page = {} 21 | $scope.artboard = {} 22 | 23 | console.log('artboard') 24 | 25 | if($scope.data.returned){ 26 | kickOff() 27 | } 28 | $scope.$watch('data.returned', function(){ 29 | if(lodash.isEmpty( $scope.data.pages ) ) return false 30 | kickOff() 31 | }) 32 | 33 | function kickOff(){ 34 | 35 | $scope.page = lodash.find( $scope.data.pages, { id: $scope.pageId }) 36 | 37 | $scope.artboard = lodash.find( $scope.page.artboards, { id: $scope.artboardId }) 38 | 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /app/modules/artboard/directives/artboard.directive.js: -------------------------------------------------------------------------------- 1 | 2 | const directiveTemplate = require('./artboard.tpl.html') 3 | 4 | module.exports = () => { 5 | 6 | return { 7 | scope: { 8 | pageId: '@', 9 | artboardId: '@' 10 | }, 11 | restrict: 'E', 12 | replace: false, 13 | template: directiveTemplate, 14 | controller: 'artboardCtrl', 15 | controllerAs: 'ctrl' 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /app/modules/artboard/directives/artboard.tpl.html: -------------------------------------------------------------------------------- 1 |
2 |
{{artboard.name}} ( {{artboard.rect.width}} x {{artboard.rect.height}} )
3 |
4 | 5 |
6 | 7 |
-------------------------------------------------------------------------------- /app/modules/artboard/index.js: -------------------------------------------------------------------------------- 1 | // artboard modules components: 2 | 3 | const controller = require('./controllers/artboard.ctrl.js') 4 | const directive = require('./directives/artboard.directive.js') 5 | 6 | module.exports = angular.module('app.artboard', [] ) 7 | .controller( 'artboardCtrl', [ '$scope', 'dataService', controller ] ) 8 | .directive( 'artboard', [ directive ] ) 9 | -------------------------------------------------------------------------------- /app/modules/artboard/styles/artboard.scss: -------------------------------------------------------------------------------- 1 | // Module styling 2 | 3 | .artboard-page { 4 | 5 | .light { 6 | opacity: .4; 7 | } 8 | 9 | .img-container { 10 | text-align: center; 11 | } 12 | 13 | } -------------------------------------------------------------------------------- /app/modules/data/index.js: -------------------------------------------------------------------------------- 1 | // data modules components: 2 | 3 | var service = require('./services/data.service.js'); 4 | 5 | 6 | 7 | module.exports = angular.module('app.data', []) 8 | .service('dataService', [ '$http', '$state', service ]); -------------------------------------------------------------------------------- /app/modules/data/services/data.service.js: -------------------------------------------------------------------------------- 1 | 2 | const lodash = require('lodash') 3 | 4 | module.exports = function( $http, $state ){ 5 | return { 6 | data: { 7 | returned: false, 8 | scale: 100, 9 | pages: [], 10 | currentPage: 0, 11 | updateCurrentPage: function(){ 12 | if( this.pages.length < 1 ) return false 13 | this.currentPage = lodash.indexOf( this.pages, lodash.find( this.pages, { id: $state.params.id })) 14 | if( this.currentPage == -1 ) this.currentPage = 0 15 | } 16 | }, 17 | get: function( callback ){ 18 | console.log('getting..', this) 19 | return $http({ 20 | method: 'GET', 21 | withCredentials: true, 22 | url: 'data.json' 23 | }).then(( res ) => { 24 | this.data.pages = lodash.reject(res.data.pages, { name: 'Symbols' }) 25 | this.data.updateCurrentPage() 26 | this.data.returned = true 27 | }) 28 | } 29 | }; 30 | }; -------------------------------------------------------------------------------- /app/modules/nav/controllers/nav.ctrl.js: -------------------------------------------------------------------------------- 1 | // pages controller: 2 | 3 | const lodash = require('lodash') 4 | 5 | module.exports = ( $scope, $state, dataService ) => { 6 | 7 | var self = this 8 | 9 | console.log('SS', $state.params.id) 10 | 11 | this.data = {} 12 | this.data = dataService.data 13 | 14 | dataService.get() 15 | 16 | return this 17 | 18 | } -------------------------------------------------------------------------------- /app/modules/nav/directives/nav.directive.js: -------------------------------------------------------------------------------- 1 | 2 | const directiveTemplate = require('./nav.tpl.html') 3 | 4 | module.exports = () => { 5 | 6 | return { 7 | scope: { }, 8 | restrict: 'E', 9 | replace: false, 10 | template: directiveTemplate, 11 | controller: 'navCtrl', 12 | controllerAs: 'ctrl' 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /app/modules/nav/directives/nav.tpl.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/modules/nav/index.js: -------------------------------------------------------------------------------- 1 | // nav modules components: 2 | 3 | const controller = require('./controllers/nav.ctrl.js') 4 | const directive = require('./directives/nav.directive.js') 5 | 6 | module.exports = angular.module('app.nav', [] ) 7 | .controller( 'navCtrl', [ '$scope', '$state', 'dataService', controller ] ) 8 | .directive( 'navbar', [ directive ] ) 9 | -------------------------------------------------------------------------------- /app/modules/nav/styles/nav.scss: -------------------------------------------------------------------------------- 1 | // Module styling 2 | 3 | #navbar-wrapper { 4 | height: 80px; 5 | } 6 | 7 | #navbar { 8 | position: fixed; 9 | left: 0; 10 | top: 0; 11 | right: 0; 12 | z-index: 3; 13 | background-color: #fff; 14 | } -------------------------------------------------------------------------------- /app/modules/page/controllers/page.ctrl.js: -------------------------------------------------------------------------------- 1 | // page controller: 2 | 3 | const lodash = require('lodash') 4 | const q = require('q') 5 | const Hamster = require('hamsterjs') 6 | const $ = require('jquery') 7 | 8 | module.exports = ( $scope, dataService, $rootScope, $state ) => { 9 | 10 | 11 | const ZOOM_PER_TICK = 20 12 | const INITIAL_SCALE = 80 13 | const TEXT_FILL_OFFSET = 40 14 | 15 | 16 | $scope.data = dataService.data 17 | $scope.page = {} 18 | let self = {} 19 | let maxx, maxy; 20 | 21 | $scope.minScale = 20 22 | $scope.maxScale = 400 23 | 24 | let boardContents = $('#boardcontents') 25 | let boardlayout = $('#boardlayout') 26 | $scope.data.scale = INITIAL_SCALE 27 | 28 | let boardlayoutWidth = parseInt( boardlayout.width(), false ) || 0 29 | let boardlayoutHeight = parseInt( boardlayout.height(), false ) || 0 30 | 31 | $scope.dblClick = function( board ){ 32 | console.log('Board:', board) 33 | $state.go('pages.page.artboard', { 34 | id: $scope.page.id, 35 | artboard: board.id 36 | }) 37 | } 38 | 39 | if($scope.data.returned){ 40 | kickOff() 41 | } 42 | $scope.$watch('data.returned', function(){ 43 | if(lodash.isEmpty( $scope.data.pages ) ) return false 44 | kickOff() 45 | }) 46 | 47 | function centerContents(){ 48 | updateLayoutWidth() 49 | if(boardlayoutWidth == 0){ 50 | setTimeout( centerContents.bind( this ), 40 ) 51 | } 52 | // If the content is bigger than the page width: 53 | if( boardlayoutWidth < maxx ) return false 54 | 55 | let midCont = ( maxx / 2 ) * ( $scope.data.scale / 100 ) 56 | boardContents.css({ 57 | left: ( ( boardlayoutWidth / 2 ) - midCont ) 58 | }) 59 | } 60 | 61 | function kickOff(){ 62 | 63 | let page = lodash.find( $scope.data.pages, { id: $scope.pageId }) 64 | 65 | let minx = lodash.min( lodash.map( page.artboards, ( b ) => lodash.get(b, 'rect.x') ) ) 66 | let miny = lodash.min( lodash.map( page.artboards, ( b ) => lodash.get(b, 'rect.y') ) ) 67 | 68 | // console.log('xx', ) 69 | maxx = ( lodash.max( lodash.map( page.artboards, ( b ) => b.rect.x + b.rect.width ) ) + Math.abs(minx) ) 70 | maxy = ( lodash.max( lodash.map( page.artboards, ( b ) => b.rect.y + b.rect.height ) ) + Math.abs(miny) ) 71 | 72 | boardContents.css({ width: maxx, height: maxy }) 73 | 74 | updateLayoutWidth() 75 | page.artboards = lodash.map( page.artboards, ( board ) => { 76 | board.rect.x -= minx 77 | board.rect.y -= miny 78 | return board 79 | }) 80 | $scope.page = page 81 | centerContents() 82 | 83 | } 84 | 85 | 86 | boardlayout.bind('mousemove', function( e ){ 87 | self.panEndX = e.pageX 88 | self.panEndY = e.pageY 89 | if(self.mouseDown){ 90 | var pageTop = self.pageTop 91 | var pageLeft = self.pageLeft 92 | self.panTop = self.panEndY - self.panStartY 93 | self.panLeft = self.panEndX - self.panStartX 94 | pageTop += self.panTop 95 | pageLeft += self.panLeft 96 | boardContents.css({ top: pageTop, left: pageLeft }) 97 | } 98 | }) 99 | boardlayout.bind('mousedown', function( e ){ 100 | e.preventDefault() 101 | self.panStartX = e.pageX 102 | self.panStartY = e.pageY 103 | self.pageTop = parseInt(boardContents.css('top'), false) || 0 104 | self.pageLeft = parseInt(boardContents.css('left'), false) || 0 105 | self.mouseDown = true 106 | }) 107 | boardlayout.bind('mouseup', function(){ 108 | self.mouseDown = false 109 | }) 110 | 111 | function updateLayoutWidth(){ 112 | boardlayoutWidth = parseInt( boardlayout.width(), false ) || 0 113 | boardlayoutHeight = parseInt( boardlayout.height(), false ) || 0 114 | } 115 | 116 | $scope.didChange = function(){ 117 | scalePage() 118 | } 119 | 120 | $rootScope.$on('zoom', ( e, params ) => { 121 | const { direction, event } = params 122 | directionScale( direction ) 123 | $scope.$apply() 124 | }) 125 | 126 | $scope.clickZoom = function( direction ){ 127 | directionScale( direction ) 128 | } 129 | 130 | function directionScale( direction ){ 131 | if(direction == 'in') 132 | $scope.data.scale += ZOOM_PER_TICK 133 | else 134 | $scope.data.scale -= ZOOM_PER_TICK 135 | scalePage() 136 | } 137 | 138 | Hamster( boardlayout[0] ).wheel(function( event, delta, deltaX, deltaY ){ 139 | $scope.data.scale += deltaY 140 | scalePage() 141 | $scope.$apply() 142 | }) 143 | 144 | function scalePage(){ 145 | 146 | updateLayoutWidth() 147 | 148 | let offset = boardContents.offset() 149 | let pageWidth = parseInt(boardContents.css('width'), false) || 0 150 | let pageHeight = parseInt(boardContents.css('height'), false) || 0 151 | 152 | offset.top = offset.top - 49 // top bar has to be counted 153 | offset.left = offset.left - ( offset.left * 2 ) 154 | offset.top = offset.top - ( offset.top * 2 ) 155 | 156 | let halfScreenx = ( boardlayoutWidth / 2 ) 157 | let halfScreeny = ( boardlayoutHeight / 2 ) 158 | let toLeft = ( offset.left + halfScreenx ) 159 | let toTop = ( offset.top + halfScreeny ) 160 | 161 | 162 | if( $scope.data.scale <= $scope.minScale ) $scope.data.scale = $scope.minScale+0 163 | if( $scope.data.scale >= $scope.maxScale ) $scope.data.scale = $scope.maxScale+0 164 | // $scope.data.scale = parseFloat( parseFloat($scope.data.scale).toFixed(2) ) 165 | 166 | let offsetPercx = ( toLeft / pageWidth ) 167 | let offsetPercy = ( toTop / pageHeight ) 168 | let newToLeft = ( ( ( ( maxx * ( $scope.data.scale / 100 ) ) * offsetPercx ) - halfScreenx ) ) 169 | let newToTop = ( ( ( ( maxy * ( $scope.data.scale / 100 ) ) * offsetPercy ) - halfScreeny ) ) 170 | 171 | newToLeft = newToLeft - ( newToLeft * 2 ) 172 | newToTop = newToTop - ( newToTop * 2 ) 173 | 174 | // console.log('SET', $scope.data.scale, `${toLeft}px 600px`) 175 | boardContents.css({ 176 | left: `${newToLeft}px`, 177 | top: `${newToTop}px`, 178 | transform: `scale(${$scope.data.scale/100},${$scope.data.scale/100})` 179 | }) 180 | 181 | } 182 | 183 | } -------------------------------------------------------------------------------- /app/modules/page/directives/page.directive.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | const directiveTemplate = require('./page.tpl.html') 4 | const lodash = require('lodash') 5 | const q = require('q') 6 | const Hamster = require('hamsterjs') 7 | const $ = require('jquery') 8 | 9 | module.exports = ( dataService, $state, $rootScope ) => { 10 | 11 | return { 12 | scope: { 13 | pageId: '@', 14 | scale: '@' 15 | }, 16 | restrict: 'E', 17 | replace: false, 18 | template: directiveTemplate, 19 | controller: 'pageCtrl' 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /app/modules/page/directives/page.tpl.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 | 6 |
7 |
8 |
Scale: {{data.scale}}%
9 | 10 |
11 |
12 | 13 |
14 |
15 |
16 | 18 |
19 | 20 |
21 |
{{board.name}}
22 | 23 |
24 |
25 |
26 |
-------------------------------------------------------------------------------- /app/modules/page/index.js: -------------------------------------------------------------------------------- 1 | // page modules components: 2 | 3 | const controller = require('./controllers/page.ctrl.js') 4 | const directive = require('./directives/page.directive.js') 5 | 6 | module.exports = angular.module('app.page', [] ) 7 | .controller( 'pageCtrl', [ '$scope', 'dataService', '$rootScope', '$state', controller ] ) 8 | .directive( 'page', [ directive ] ) 9 | -------------------------------------------------------------------------------- /app/modules/page/styles/page.scss: -------------------------------------------------------------------------------- 1 | // Module styling 2 | 3 | #boardlayout { 4 | overflow: hidden; 5 | position: absolute; 6 | top: 49px; 7 | left: 0px; 8 | -webkit-transform-style: preserve-3d; 9 | right: 0px; 10 | bottom: 0px; 11 | } 12 | 13 | #zoom-buttons { 14 | position: fixed; 15 | bottom: 0; 16 | left: 50%; 17 | width: 400px; 18 | margin-left: -220px; 19 | z-index: 6; 20 | background: rgba(255,255,255,0.7); 21 | padding: 0px 20px; 22 | user-select: none; 23 | } 24 | 25 | #boardcontents { 26 | position: absolute; 27 | // -webkit-transform-style: preserve-3d; 28 | left: 5%; 29 | top: 5%; 30 | width: 100%; 31 | height: 100%; 32 | transform-origin: 0 0; 33 | transform: scale( .8, .8 ); 34 | cursor: move; 35 | .md-headline { 36 | padding-bottom: 8px; 37 | } 38 | } 39 | 40 | .scale-button { 41 | padding: 8px; 42 | margin-top: 14px; 43 | } 44 | .scale-title { 45 | padding-top: 12px; 46 | text-align: center; 47 | } 48 | .boarditem { 49 | position: absolute; 50 | img { 51 | image-rendering: auto; 52 | } 53 | } -------------------------------------------------------------------------------- /app/modules/pages/pages.tpl.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |

Select a Page to view

4 | 5 |
-------------------------------------------------------------------------------- /app/styles/app.scss: -------------------------------------------------------------------------------- 1 | 2 | 3 | $font-family: 'Roboto', 'Helvetica Nueue', 'Arial'; 4 | 5 | // Font Icons: 6 | $fa-font-path: 'fonts/'; 7 | @import "font-awesome/scss/font-awesome.scss"; 8 | @import "angular-material/angular-material.scss"; 9 | 10 | -------------------------------------------------------------------------------- /cli.js: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env node 2 | 3 | const DIR = process.cwd() 4 | let OPS = {} 5 | 6 | const lodash = require('lodash') 7 | const argv = require('optimist').argv 8 | const path = require('path') 9 | const gulp = require('gulp') 10 | 11 | 12 | OPS.input = argv.input 13 | OPS.output = argv.output || 'public/' 14 | OPS.open = argv.open || false 15 | 16 | if( lodash.isEmpty( OPS.input ) ){ 17 | console.error( "No input file defined. Use --input=filename.sketch" ) 18 | return process.exit( 1 ) 19 | } 20 | 21 | const exe = require('./main.js')( OPS, gulp ) 22 | exe(function(){ 23 | console.log('All Done!') 24 | }) -------------------------------------------------------------------------------- /gulpfile.js/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | process.OPS = process.OPS || {} 4 | 5 | // passed in ops: 6 | let gulp = process.gulp || require('gulp') 7 | const lodash = require('lodash') 8 | const browserSync = require('browser-sync') 9 | const gulpSequence = require('gulp-sequence').use( gulp ) 10 | const requireDir = require('require-dir') 11 | const path = require('path') 12 | 13 | 14 | const vendors = [ 15 | 'angular', 16 | 'angular-ui-router', 17 | 'angular-animate', 18 | 'angular-aria', 19 | 'angular-material', 20 | 'jquery', 21 | 'lodash' 22 | ] 23 | 24 | var config = { 25 | app: './app', 26 | dest: process.OPS.outputPath || './public', 27 | uiPort: 5000, 28 | tasks: { 29 | sass: { 30 | dest: 'styles', 31 | paths: [ 32 | 'node_modules/', 33 | '../../node_modules/', 34 | 'node_modules/font-awesome/scss' 35 | ], 36 | artifacts: { 37 | 'app': { 38 | src: [ 39 | path.resolve(__dirname, '../')+'/app/styles/app.scss', 40 | path.resolve(__dirname, '../')+'/app/modules/**/*.scss' 41 | ] 42 | } 43 | } 44 | }, 45 | webpack: { 46 | src: '', 47 | dest: '', 48 | artifacts: { 49 | app: './app', 50 | vendors: vendors 51 | }, 52 | output: '[name].bundle.js', 53 | loaders: [ 54 | { test: /\.html$/, loader: 'raw' }, 55 | { 56 | test: /\.js$/, 57 | exclude: /(node_modules|bower_components)/, 58 | loader: 'babel-loader', // 'babel-loader' is also a legal name to reference 59 | query: { 60 | presets: ['es2015-script'] 61 | } 62 | }], 63 | noParse: vendors 64 | }, 65 | html: { 66 | src: '*.html' 67 | }, 68 | images: { 69 | src: [ 70 | path.resolve(__dirname, '../')+'/app/images/**/*.+(png|jpg|gif|jpeg)', 71 | process.cwd()+'/_artboards/**/*.+(png|jpg|gif|jpeg)' 72 | ], 73 | dest: 'images' 74 | }, 75 | fonts: { 76 | src: [ 77 | 'node_modules/font-awesome/fonts/**/*', 78 | '../../node_modules/font-awesome/fonts/**/*' 79 | ], 80 | dest: 'styles/fonts' 81 | } 82 | } 83 | } 84 | 85 | // console.log('D', __dirname, process.cwd()) 86 | // return console.log('config', JSON.stringify(config, null, 4) ) 87 | 88 | let env = 'dev' 89 | const falsy = /^(?:f(?:alse)?|no?|0+)$/i 90 | Boolean.parse = (val) => { 91 | return !falsy.test(val) && !!val; 92 | } 93 | 94 | // custom additions to ops: 95 | let ops = {} 96 | ops.gulp = gulp 97 | ops.config = config 98 | ops.browserSync = browserSync 99 | // ops.program = program 100 | ops.gulpSequence = gulpSequence 101 | ops.prod = function(){ 102 | return false 103 | } 104 | ops.env = env 105 | 106 | 107 | // Require all tasks in gulpfile.js/tasks, including subfolders 108 | let tasks = requireDir( './tasks' ) 109 | 110 | // load each gulp task and pass it ops: 111 | tasks = lodash.each( tasks, (task) => task( ops ) ) 112 | -------------------------------------------------------------------------------- /gulpfile.js/tasks/browserSync.js: -------------------------------------------------------------------------------- 1 | 2 | const notify = require('gulp-notify') 3 | const lodash = require('lodash') 4 | 5 | 6 | module.exports = function( ops ){ 7 | 8 | const gulp = ops.gulp 9 | const config = ops.config 10 | const browserSync = ops.browserSync 11 | 12 | const settings = config.browserSync || { 13 | server: { 14 | baseDir: config.dest, 15 | }, 16 | notify: false, 17 | ghostMode: false, 18 | port: config.uiPort, 19 | } 20 | 21 | const browserSyncTask = function( cb ){ 22 | browserSync.init( settings ) 23 | 24 | gulp.watch([ 25 | config.dest+"/**/*.html", 26 | ]).on( 'change', browserSync.reload ) 27 | } 28 | 29 | gulp.task( 'browserSync', browserSyncTask ) 30 | 31 | return browserSyncTask 32 | 33 | } -------------------------------------------------------------------------------- /gulpfile.js/tasks/build.js: -------------------------------------------------------------------------------- 1 | 2 | const notify = require('gulp-notify') 3 | const lodash = require('lodash') 4 | 5 | 6 | module.exports = function( ops ){ 7 | 8 | let gulp = ops.gulp 9 | const config = ops.config 10 | const browserSync = ops.browserSync 11 | const gulpSequence = ops.gulpSequence 12 | 13 | gulp.task('build', function( cb ){ 14 | 15 | process.env.prod = true 16 | 17 | // callback if nothing else 18 | gulp._cb = gulp._cb || function(){ cb() } 19 | 20 | console.log('build') 21 | 22 | let tasks = [ 23 | 'sass', 24 | 'html', 25 | 'webpack:production', 26 | 'generate-data', 27 | 'fonts' 28 | ] 29 | 30 | // Running as a global CLI: 31 | if( process.OPS.open ){ 32 | return gulpSequence( 'clean', tasks, 'images', 'browserSync', gulp._cb) 33 | } 34 | return gulpSequence( 'clean', tasks, 'images', gulp._cb) 35 | 36 | }) 37 | 38 | } -------------------------------------------------------------------------------- /gulpfile.js/tasks/clean.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | const clean = require('rimraf') 4 | const mkdirp = require('mkdirp') 5 | const path = require('path') 6 | 7 | module.exports = function( ops ){ 8 | 9 | const gulp = ops.gulp 10 | const config = ops.config 11 | 12 | gulp.task('clean-artboards', function( cb ){ 13 | let _path = path.resolve( config.dest, '../_artboards' ) 14 | if(process.OPS.input){ 15 | _path = path.resolve( process.OPS.outputPath, '../_artboards' ) 16 | } 17 | clean( _path, cb ) 18 | }) 19 | 20 | gulp.task('clean', [ 'clean-artboards' ], function( cb ){ 21 | clean(config.dest, ( err ) => { 22 | mkdirp(config.dest, cb) 23 | }) 24 | }) 25 | 26 | } -------------------------------------------------------------------------------- /gulpfile.js/tasks/default.js: -------------------------------------------------------------------------------- 1 | 2 | const notify = require('gulp-notify') 3 | const lodash = require('lodash') 4 | 5 | 6 | module.exports = function( ops ){ 7 | 8 | const gulp = ops.gulp 9 | const config = ops.config 10 | const browserSync = ops.browserSync 11 | const gulpSequence = ops.gulpSequence 12 | 13 | gulp.task('default', function( cb ){ 14 | 15 | console.log('Default task') 16 | process.env.prod = false 17 | return gulpSequence( 'clean', [ 'generate-data', 'sass:watch', 'html:watch', 'webpack:watch', 'fonts:watch' ], 'images:watch', 'browserSync', cb ) 18 | 19 | }) 20 | 21 | } -------------------------------------------------------------------------------- /gulpfile.js/tasks/fonts.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | module.exports = function( ops ){ 5 | 6 | const gulp = ops.gulp 7 | const config = ops.config 8 | const env = ops.env 9 | 10 | const browserSync = ops.browserSync 11 | 12 | if(!config.tasks.fonts) return 13 | 14 | const lodash = require('lodash') 15 | const path = require('path') 16 | const notify = require('gulp-notify') 17 | const changed = require('gulp-changed') 18 | 19 | const sources = lodash.map( config.tasks.fonts.src, ( src ) => { 20 | return path.resolve( __dirname, '../../', src ) 21 | }) 22 | 23 | const paths = { 24 | src: sources, 25 | dest: path.resolve( config.dest, config.tasks.fonts.dest ) 26 | } 27 | 28 | const fontsTask = function( cb ){ 29 | const PROD = Boolean.parse(process.env.prod) 30 | let stream = gulp.src( paths.src ) 31 | .pipe(changed(paths.dest)) 32 | .pipe(gulp.dest(paths.dest)) 33 | if(!PROD) 34 | stream = stream.pipe( browserSync.stream() ) 35 | return stream 36 | } 37 | 38 | gulp.task('fonts', fontsTask) 39 | gulp.task('fonts:watch', ['fonts'], function(){ 40 | return gulp.watch( paths.src, ['fonts'] ) 41 | }) 42 | return fontsTask 43 | 44 | } -------------------------------------------------------------------------------- /gulpfile.js/tasks/generate-data.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | const fs = require('fs') 4 | const exec = require('child_process').exec 5 | const path = require('path') 6 | 7 | module.exports = function( ops ){ 8 | 9 | const gulp = ops.gulp; 10 | const config = ops.config; 11 | 12 | const BIN = path.resolve( __dirname, '../../sketchtool/bin/sketchtool' ) 13 | 14 | function getParams(){ 15 | if( process.OPS.input ){ 16 | return { 17 | exportDir: path.resolve( process.OPS.outputPath, '../_artboards' ), 18 | jsonDir: path.resolve( process.OPS.outputPath, './data.json' ), 19 | sketchFile: process.OPS.inputFile 20 | } 21 | }else{ 22 | return { 23 | exportDir: path.resolve( config.app, '../_artboards' ), 24 | jsonDir: path.resolve( config.app, '../public/data.json' ), 25 | sketchFile: path.resolve( config.app, '../sketch/social-app-ui-kit.sketch' ) 26 | } 27 | } 28 | } 29 | 30 | gulp.task( 'export-images', function( cb ){ 31 | const { exportDir, jsonDir, sketchFile } = getParams() 32 | exec( `${BIN} export artboards --include-symbols --output=${exportDir} --scales=2.0 --use-id-for-name=YES --format=jpg ${sketchFile}`, cb ) 33 | }) 34 | 35 | gulp.task( 'generate-data', [ 'export-images' ], function( cb ){ 36 | const { exportDir, jsonDir, sketchFile } = getParams() 37 | exec( `${BIN} list artboards ${sketchFile}`, ( err, out ) => { 38 | let json = JSON.parse( out ) 39 | fs.writeFileSync( jsonDir, out ) 40 | cb(err) 41 | }) 42 | 43 | }); 44 | 45 | }; -------------------------------------------------------------------------------- /gulpfile.js/tasks/gh-pages.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | module.exports = function( ops ){ 7 | 8 | const gulp = ops.gulp 9 | const config = ops.config 10 | const ghPages = require('gulp-gh-pages') 11 | 12 | gulp.task('deploy', ['build'], function(){ 13 | return gulp.src( config.dest+'/**/*' ) 14 | .pipe(ghPages()) 15 | }) 16 | 17 | } -------------------------------------------------------------------------------- /gulpfile.js/tasks/html.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | const path = require('path') 4 | const notify = require('gulp-notify') 5 | 6 | module.exports = function( ops ){ 7 | 8 | const gulp = ops.gulp 9 | const config = ops.config 10 | const env = ops.env 11 | const browserSync = ops.browserSync 12 | 13 | const paths = { 14 | src: path.resolve( __dirname, '../../', config.app, config.tasks.html.src ), 15 | dest: path.resolve( config.dest ) 16 | } 17 | 18 | const htmlTask = function(){ 19 | const PROD = Boolean.parse(process.env.prod) 20 | let stream = gulp.src( paths.src ) 21 | .pipe(gulp.dest( paths.dest )) 22 | if(!PROD) 23 | stream = stream.pipe(browserSync.stream()) 24 | return stream 25 | } 26 | 27 | gulp.task('html', htmlTask) 28 | gulp.task('html:watch', ['html'], function(){ 29 | return gulp.watch( paths.src, ['html'] ) 30 | }) 31 | 32 | return htmlTask 33 | 34 | } 35 | -------------------------------------------------------------------------------- /gulpfile.js/tasks/images.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | module.exports = function( ops ){ 4 | 5 | const gulp = ops.gulp 6 | const config = ops.config 7 | const env = ops.env 8 | const browserSync = ops.browserSync 9 | 10 | if(!config.tasks.images) return 11 | 12 | const lodash = require('lodash') 13 | const imagemin = require('gulp-imagemin') 14 | const path = require('path') 15 | const notify = require('gulp-notify') 16 | const changed = require('gulp-changed') 17 | 18 | 19 | const sources = lodash.map(config.tasks.images.src, function( src ){ 20 | return path.join( src ) 21 | }) 22 | 23 | const paths = { 24 | src: sources, 25 | dest: path.resolve(config.dest, config.tasks.images.dest) 26 | } 27 | 28 | const imagesTask = function(){ 29 | const PROD = Boolean.parse(process.env.prod) 30 | let stream = gulp.src(paths.src) 31 | .pipe(changed(paths.dest)) // Ignore unchanged files 32 | .pipe(imagemin({ 33 | optimizationLevel: 5, 34 | progressive: true, 35 | interlaced: true 36 | })) // Optimize 37 | .pipe(gulp.dest(paths.dest)) 38 | if(!PROD) 39 | stream = stream.pipe(browserSync.stream()) 40 | return stream 41 | } 42 | 43 | gulp.task('images', imagesTask) 44 | gulp.task('images:watch', ['images'], function(){ 45 | return gulp.watch( paths.src, ['images'] ) 46 | }) 47 | return imagesTask 48 | 49 | } -------------------------------------------------------------------------------- /gulpfile.js/tasks/scss.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | module.exports = function( ops ){ 4 | 5 | const gulp = ops.gulp 6 | const config = ops.config 7 | const env = ops.env 8 | const browserSync = ops.browserSync 9 | 10 | if(!config.tasks.sass) return 11 | 12 | const path = require('path') 13 | const lodash = require('lodash') 14 | const minifyCSS = require('gulp-minify-css') 15 | const sourcemaps = require('gulp-sourcemaps') 16 | const sass = require('gulp-sass') 17 | const concat = require('gulp-concat') 18 | const notify = require('gulp-notify') 19 | 20 | let tasks = [] 21 | const DEST = path.resolve( config.dest, config.tasks.sass.dest ) 22 | 23 | const sassTask = function( artifact, output ){ 24 | 25 | const PROD = Boolean.parse(process.env.prod) 26 | 27 | const filename = output+'.css' 28 | const paths = lodash.map(config.tasks.sass.paths, function(dir){ 29 | return path.resolve( __dirname, '../../', dir ) 30 | }) 31 | 32 | let stream = gulp.src( artifact.src ) 33 | 34 | if(!PROD){ 35 | stream = stream.pipe(sourcemaps.init()) 36 | } 37 | 38 | stream = stream.pipe(sass({ 39 | includePaths: paths 40 | }).on('error', notify.onError(function(err){ 41 | return { 42 | title: '', 43 | 'subtitle': 'SASS Error', 44 | 'message': err.message, 45 | 'icon': path.resolve(__dirname, 'app/images/logo.png'), // case sensitive 46 | } 47 | }))).pipe(concat( filename )) 48 | 49 | if(PROD){ 50 | stream = stream.pipe(minifyCSS()) 51 | }else{ 52 | // sourcemap LESS files, easy debugging: 53 | stream = stream.pipe(sourcemaps.write('.')) 54 | } 55 | stream = stream.pipe(gulp.dest(DEST)) 56 | return stream 57 | } 58 | 59 | 60 | const sassTask_Watch = function( cb ){ 61 | lodash.each(config.tasks.sass.artifacts, function( artifact, output ){ 62 | gulp.watch(artifact.src, ['sass-'+output]) 63 | }) 64 | // Inject on css changes in destination directory: 65 | gulp.watch([DEST+'/**/*.css']).on('change', function(){ 66 | gulp.src(DEST+'/**/*.css') 67 | .pipe(browserSync.stream()) 68 | }) 69 | cb() 70 | } 71 | 72 | lodash.each(config.tasks.sass.artifacts, function( artifact, output ){ 73 | const task = 'sass-'+output 74 | gulp.task(task, function(){ 75 | return sassTask( artifact, output ) 76 | }) 77 | tasks.push(task) 78 | }) 79 | 80 | gulp.task('sass', tasks) 81 | gulp.task('sass:watch', ['sass'], sassTask_Watch) 82 | return sassTask 83 | 84 | } 85 | -------------------------------------------------------------------------------- /gulpfile.js/tasks/webpack.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | module.exports = function( ops ){ 5 | 6 | const gulp = ops.gulp 7 | const config = ops.config 8 | const env = ops.env 9 | const browserSync = ops.browserSync 10 | let initialCompile = false 11 | 12 | if(!config.tasks.webpack) return 13 | 14 | const path = require('path') 15 | const lodash = require('lodash') 16 | const notify = require('gulp-notify') 17 | const webpack = require('webpack') 18 | const raw = require('raw-loader') 19 | 20 | var getOptions = function( PROD ){ 21 | 22 | PROD = PROD || Boolean.parse( process.env.prod ) 23 | const context = path.resolve( __dirname, '../../', config.app, config.tasks.webpack.src ) 24 | const dest = path.resolve( config.dest, 'js' ) 25 | const modulesDirectories = path.resolve( __dirname, '../../node_modules/' ) 26 | 27 | // Default DEV settings: 28 | let options = { 29 | context: context, 30 | entry: config.tasks.webpack.artifacts, 31 | output: { 32 | path: dest, 33 | filename: config.tasks.webpack.output, 34 | publicPath: '/js/' 35 | }, 36 | node: { 37 | fs: 'empty' 38 | }, 39 | resolve: { 40 | root: [ context ], 41 | // modulesDirectories: [ modulesDirectories ], 42 | alias: config.tasks.webpack.alias 43 | }, 44 | module: { 45 | loaders: config.tasks.webpack.loaders 46 | }, 47 | plugins: [ 48 | new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors.bundle.js'), 49 | new webpack.DefinePlugin({ 50 | VER: '123', 51 | PROD: false 52 | }), 53 | // new webpack.ProvidePlugin({ 54 | // d3: 'd3' 55 | // }) 56 | ], 57 | noParse: config.tasks.webpack.noParse || [] 58 | } 59 | 60 | // PROD options ( minify, etc ) 61 | if(PROD === true){ 62 | options.plugins.push( 63 | // Minify the compiled JS: 64 | new webpack.optimize.UglifyJsPlugin({ 65 | sourceMap: false, 66 | mangle: false 67 | }) 68 | ) 69 | options.plugins.push( 70 | // Make sure we dont have dupes: 71 | new webpack.optimize.DedupePlugin() 72 | ) 73 | 74 | // Strip out console.log for prod: 75 | // options.module.loaders.push({ 76 | // test: /\.js$/, 77 | // loader: 'strip-loader?strip[]=console.log' 78 | // }) 79 | } else{ 80 | options.devtool = 'source-map' 81 | } 82 | 83 | return options 84 | } 85 | 86 | // Dev version: 87 | const webPackTask_Watch = function( callback ){ 88 | const options = getOptions() 89 | const WPAC = webpack(options).watch(200, function(err, stats){ 90 | if( !lodash.isEmpty( stats.compilation.errors ) ){ 91 | console.log('ERROR:', stats.compilation.errors[0].message) 92 | notify({ 93 | title: '', 94 | 'subtitle': 'WebPack Error', 95 | 'message': stats.compilation.errors[0].message, 96 | 'icon': path.join(__dirname, 'app/images/logo.png'), // case sensitive 97 | }) 98 | } 99 | browserSync.reload() 100 | // On the initial compile, let gulp know the task is done 101 | if(!initialCompile){ 102 | initialCompile = true 103 | callback() 104 | } 105 | }) 106 | } 107 | 108 | // Prod version: 109 | const webPackTask_Production = function( callback ){ 110 | const options = getOptions(true) 111 | const WPAC = webpack(options, function(err, stats){ 112 | // logger(err, stats) 113 | if( !lodash.isEmpty( stats.compilation.errors ) ){ 114 | console.log('ERROR:', stats.compilation.errors[0].message) 115 | notify({ 116 | title: '', 117 | 'subtitle': 'WebPack Error', 118 | 'message': stats.compilation.errors[0].message, 119 | 'icon': path.join(__dirname, 'app/images/logo.png'), // case sensitive 120 | }) 121 | } 122 | callback(err) 123 | }) 124 | } 125 | 126 | gulp.task('webpack:watch', webPackTask_Watch) 127 | gulp.task('webpack:production', webPackTask_Production) 128 | 129 | return { 130 | getOptions: getOptions 131 | } 132 | 133 | } 134 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | 2 | const path = require('path') 3 | 4 | module.exports = function( OPS, gulp ){ 5 | 6 | OPS.inputFile = path.resolve( process.cwd(), OPS.input ) 7 | OPS.outputPath = path.resolve( process.cwd(), ( OPS.output || 'public/' ) ) 8 | 9 | process.OPS = OPS 10 | process.gulp = gulp 11 | 12 | require('./gulpfile.js/index.js') 13 | 14 | return function( cb ){ 15 | console.log('Generating Sketch Preview... Please be patient') 16 | gulp._cb = cb 17 | gulp.start('build') 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sketch-preview", 3 | "version": "1.0.9", 4 | "description": "Sketch UI Generator", 5 | "main": "main.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "./node_modules/gulp/bin/gulp.js build" 9 | }, 10 | "bin": { 11 | "sketch-preview": "./cli.js" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/stackdot/sketch-preview.git" 16 | }, 17 | "bugs": { 18 | "url": "https://github.com/stackdot/sketch-preview/issues" 19 | }, 20 | "homepage": "https://github.com/stackdot/sketch-preview#readme", 21 | "engineStrict": true, 22 | "engines": { 23 | "node": ">6.0.0" 24 | }, 25 | "preferGlobal": true, 26 | "author": "", 27 | "tags": [ 28 | "angular", 29 | "material", 30 | "stackdot", 31 | "sketch", 32 | "sketchapp", 33 | "design", 34 | "tools" 35 | ], 36 | "license": "MIT", 37 | "devDependencies": {}, 38 | "dependencies": { 39 | "angular": "^1.4.8", 40 | "angular-animate": "^1.4.8", 41 | "angular-aria": "^1.4.8", 42 | "angular-material": "^1.1.0-rc.5", 43 | "angular-mocks": "^1.4.8", 44 | "angular-panhandler": "^1.1.2", 45 | "angular-ui-router": "^0.2.15", 46 | "babel-core": "^6.13.2", 47 | "babel-loader": "^6.2.5", 48 | "babel-preset-es2015-script": "^1.0.0", 49 | "browser-sync": "^2.10.0", 50 | "font-awesome": "^4.5.0", 51 | "gulp": "^3.8.11", 52 | "gulp-changed": "^1.3.0", 53 | "gulp-concat": "^2.6.0", 54 | "gulp-gh-pages": "^0.5.4", 55 | "gulp-if": "^2.0.0", 56 | "gulp-imagemin": "^3.0.2", 57 | "gulp-minify-css": "^1.2.1", 58 | "gulp-notify": "^2.2.0", 59 | "gulp-sass": "^2.1.0", 60 | "gulp-sequence": "^0.4.1", 61 | "gulp-sourcemaps": "^1.6.0", 62 | "hamsterjs": "^1.1.2", 63 | "jquery": "^3.1.0", 64 | "lodash": "^4.0.0", 65 | "mkdirp": "^0.5.1", 66 | "optimist": "^0.6.1", 67 | "raw-loader": "^0.5.1", 68 | "require-dir": "^0.3.0", 69 | "rimraf": "^2.4.3", 70 | "webpack": "^1.12.4" 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /screens/generated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stackdot/sketch-preview/d2c85d6d80ef4d5f177d89bc55264e5b3137cd15/screens/generated.png -------------------------------------------------------------------------------- /screens/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stackdot/sketch-preview/d2c85d6d80ef4d5f177d89bc55264e5b3137cd15/screens/logo.png -------------------------------------------------------------------------------- /screens/sketch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stackdot/sketch-preview/d2c85d6d80ef4d5f177d89bc55264e5b3137cd15/screens/sketch.png -------------------------------------------------------------------------------- /sketch/social-app-ui-kit.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stackdot/sketch-preview/d2c85d6d80ef4d5f177d89bc55264e5b3137cd15/sketch/social-app-ui-kit.sketch -------------------------------------------------------------------------------- /sketchtool/bin/sketchmigrate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stackdot/sketch-preview/d2c85d6d80ef4d5f177d89bc55264e5b3137cd15/sketchtool/bin/sketchmigrate -------------------------------------------------------------------------------- /sketchtool/bin/sketchtool: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stackdot/sketch-preview/d2c85d6d80ef4d5f177d89bc55264e5b3137cd15/sketchtool/bin/sketchtool -------------------------------------------------------------------------------- /sketchtool/share/sketchtool/resources.bundle/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildMachineOSBuild 6 | 14F1808 7 | CFBundleDevelopmentRegion 8 | English 9 | CFBundleExecutable 10 | share/sketchtool/resources 11 | CFBundleIdentifier 12 | com.bohemiancoding.share-sketchtool-resources 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | share/sketchtool/resources 17 | CFBundlePackageType 18 | BNDL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleSupportedPlatforms 24 | 25 | MacOSX 26 | 27 | CFBundleVersion 28 | 1 29 | DTCompiler 30 | com.apple.compilers.llvm.clang.1_0 31 | DTPlatformBuild 32 | 7C1002 33 | DTPlatformVersion 34 | GM 35 | DTSDKBuild 36 | 15C43 37 | DTSDKName 38 | macosx10.11 39 | DTXcode 40 | 0721 41 | DTXcodeBuild 42 | 7C1002 43 | NSHumanReadableCopyright 44 | Copyright © 2013 Bohemian Coding. All rights reserved. 45 | 46 | 47 | -------------------------------------------------------------------------------- /sketchtool/share/sketchtool/resources.bundle/Contents/Resources/RELEASE NOTES.txt: -------------------------------------------------------------------------------- 1 | ## Sketch Tool Release Notes 2 | 3 | ### 3.5.2 4 | 5 | - Added a --include-namespaces option for SVG export. 6 | 7 | ### 3.5 8 | 9 | - Fixed a crash in the dump command when the document contains a NaN value. 10 | 11 | ### 3.4.4 12 | 13 | - Added -use-id-for-name option, which names the exported files using their id instead of their name. 14 | 15 | ### 3.4 16 | 17 | - Updated for Sketch 3.4 compatibility. 18 | - Align SketchTool and Sketch version numbers. 19 | - Fixed a crash when using the --version option. 20 | - Fixed a crash when dumping text with a non-RGB colorspace. 21 | - Added additional attribute information when dumping text layers containing multiple font styles. 22 | - Added -use-id-for-name option, which names the exported files using their id instead of their name. 23 | 24 | ### 1.4 25 | 26 | - Updated for Sketch 3.3 compatibility. 27 | - Fixed a bug where exporting layers with invalid names would crash sketchtool. We now export them as ``, so make sure to check for those in your scripts. 28 | - Fixed a bug where the export slices command would ignore IDs in --items= or --item= options. 29 | - Improved dump command output of font information. 30 | - Added 'list layers' command which outputs information on all layers in a document. 31 | - Increased the amount of information output for layers in the 'list' commands: we now output the relative and influence rects, and the rotation if there is 32 | - Documents containing images or patterns should now work ok (for a while there, they caused problems). 33 | 34 | 35 | ### 1.3 36 | 37 | - Updated for Sketch 3.2 compatibility. 38 | - Added metadata command to dump metadata for a Sketch file. 39 | - The layer list commands now include a "trimmed" rect for layers. This should indicate what the size will be if the --trimmed flag is used when exporting. 40 | - Added notes command to show these release notes. 41 | - Switched --overwriting option to -V to avoid clash with --version. 42 | - Added --background option allowing you to set/override the background colour when exporting. 43 | - Slight tweak to the code which checks for the resource bundle. 44 | - Output the x and y positions of exported slices when the --outputJSON option is on. 45 | - Added a --group-contents-only option to force the same behaviour as selecting the "Export Group Contents Only" option in a sketch slice 46 | - The dump command now includes objectID values for any model objects which have an ID assigned 47 | 48 | 49 | ### 1.2 50 | 51 | - Updated to understand Sketch 3.1 documents. 52 | - Slight tweaks to the way trimming and sizing works, which may slightly reduce the size of exported documents. 53 | - Moved support for old documents into the standalone sketchmigrate tool. 54 | - We now look for the resources in ../share/sketchtool/resources.bundle (for legacy reasons, we also still check for "sketch resources.bundle" in the old location). 55 | - Items (pages, artboards, slices etc) with slashes in their names will now correctly export into subfolders. 56 | 57 | 58 | ### 1.1.1 59 | 60 | - Added an export layers command which lets you export any layer, even if it's not been marked as exportable in the document. 61 | - Added a --compact option for SVG export which removes some of the extra crud that we would otherwise generate. 62 | - Added a --trimmed option, although it's not respected currently. 63 | - Fixed some bugs relating to the --items option. 64 | - Fixed the app name in generated SVG files. 65 | 66 | -------------------------------------------------------------------------------- /sketchtool/share/sketchtool/resources.bundle/Contents/Resources/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stackdot/sketch-preview/d2c85d6d80ef4d5f177d89bc55264e5b3137cd15/sketchtool/share/sketchtool/resources.bundle/Contents/Resources/en.lproj/InfoPlist.strings -------------------------------------------------------------------------------- /sketchtool/share/sketchtool/resources.bundle/Contents/Resources/noise-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stackdot/sketch-preview/d2c85d6d80ef4d5f177d89bc55264e5b3137cd15/sketchtool/share/sketchtool/resources.bundle/Contents/Resources/noise-1.png -------------------------------------------------------------------------------- /sketchtool/share/sketchtool/resources.bundle/Contents/Resources/noise-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stackdot/sketch-preview/d2c85d6d80ef4d5f177d89bc55264e5b3137cd15/sketchtool/share/sketchtool/resources.bundle/Contents/Resources/noise-2.png -------------------------------------------------------------------------------- /sketchtool/share/sketchtool/resources.bundle/Contents/Resources/noise-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stackdot/sketch-preview/d2c85d6d80ef4d5f177d89bc55264e5b3137cd15/sketchtool/share/sketchtool/resources.bundle/Contents/Resources/noise-3.png -------------------------------------------------------------------------------- /sketchtool/share/sketchtool/resources.bundle/Contents/Resources/noise-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stackdot/sketch-preview/d2c85d6d80ef4d5f177d89bc55264e5b3137cd15/sketchtool/share/sketchtool/resources.bundle/Contents/Resources/noise-4.png --------------------------------------------------------------------------------