├── .gitignore ├── LICENSE ├── README.md ├── content ├── README.md ├── assets │ ├── swagger-editor.png │ ├── vardyger-admin-ui-content.png │ ├── vardyger-admin-ui-editor-markdown.png │ ├── vardyger-admin-ui-editor-preview.png │ ├── vardyger-admin-ui-preview.png │ ├── vardyger-admin-ui-side-menu.png │ ├── vardyger-admin-ui-welcome-de.png │ ├── vardyger-admin-ui-welcome-en.png │ ├── vardyger-api.png │ └── vardyger-post.png └── themes │ ├── README.md │ └── casper │ ├── LICENSE │ ├── README.md │ ├── assets │ ├── css │ │ └── screen.css │ ├── fonts │ │ ├── casper-icons.eot │ │ ├── casper-icons.svg │ │ ├── casper-icons.ttf │ │ └── casper-icons.woff │ └── js │ │ ├── index.js │ │ ├── jquery.fitvids.js │ │ ├── jquery.js │ │ └── jquery.min.js │ ├── author.hbs │ ├── default.hbs │ ├── index.hbs │ ├── package.json │ ├── page.hbs │ ├── partials │ ├── loop.hbs │ └── navigation.hbs │ ├── post.hbs │ └── tag.hbs └── core ├── README.md ├── client ├── .editorconfig ├── .gitignore ├── .jshintignore ├── .jshintrc ├── Gruntfile.js ├── app │ ├── README.md │ ├── fonts │ │ ├── ionicons.eot │ │ ├── ionicons.svg │ │ ├── ionicons.ttf │ │ └── ionicons.woff │ ├── images │ │ └── ionic.png │ ├── index.html │ ├── scripts │ │ ├── app.js │ │ ├── config │ │ │ └── config.js │ │ ├── controllers │ │ │ ├── app-controller.js │ │ │ ├── editor-controller.js │ │ │ ├── login-controller.js │ │ │ ├── main-controller.js │ │ │ └── preview-controller.js │ │ ├── locales │ │ │ ├── de.json │ │ │ └── en.json │ │ └── services │ │ │ ├── authentication-service.js │ │ │ └── posts-service.js │ ├── styles │ │ ├── main.scss │ │ ├── styles.scss │ │ └── variables.scss │ └── templates │ │ ├── editor-template.html │ │ ├── login-template.html │ │ ├── main-template.html │ │ ├── preview-template.html │ │ ├── side-menu-template.html │ │ └── welcome-template.html ├── bower.json ├── config.xml ├── hooks │ ├── README.md │ ├── after_platform_add │ │ └── install_plugins.js │ ├── after_plugin_add │ │ └── register_plugins.js │ ├── after_plugin_rm │ │ └── deregister_plugins.js │ ├── after_prepare │ │ ├── icons_and_splashscreens.js │ │ └── update_platform_config.js │ └── before_platform_add │ │ └── init_directories.js ├── ionic.project ├── package.json ├── resources │ ├── android │ │ ├── drawable-hdpi │ │ │ └── icon.png │ │ ├── drawable-land-hdpi │ │ │ └── screen.png │ │ ├── drawable-land-ldpi │ │ │ └── screen.png │ │ ├── drawable-land-mdpi │ │ │ └── screen.png │ │ ├── drawable-land-xhdpi │ │ │ └── screen.png │ │ ├── drawable-ldpi │ │ │ └── icon.png │ │ ├── drawable-mdpi │ │ │ └── icon.png │ │ ├── drawable-port-hdpi │ │ │ └── screen.png │ │ ├── drawable-port-ldpi │ │ │ └── screen.png │ │ ├── drawable-port-mdpi │ │ │ └── screen.png │ │ ├── drawable-port-xhdpi │ │ │ └── screen.png │ │ ├── drawable-xhdpi │ │ │ └── icon.png │ │ ├── drawable │ │ │ └── icon.png │ │ ├── icon │ │ │ ├── drawable-hdpi-icon.png │ │ │ ├── drawable-ldpi-icon.png │ │ │ ├── drawable-mdpi-icon.png │ │ │ ├── drawable-xhdpi-icon.png │ │ │ ├── drawable-xxhdpi-icon.png │ │ │ └── drawable-xxxhdpi-icon.png │ │ └── splash │ │ │ ├── drawable-land-hdpi-screen.png │ │ │ ├── drawable-land-ldpi-screen.png │ │ │ ├── drawable-land-mdpi-screen.png │ │ │ ├── drawable-land-xhdpi-screen.png │ │ │ ├── drawable-land-xxhdpi-screen.png │ │ │ ├── drawable-land-xxxhdpi-screen.png │ │ │ ├── drawable-port-hdpi-screen.png │ │ │ ├── drawable-port-ldpi-screen.png │ │ │ ├── drawable-port-mdpi-screen.png │ │ │ ├── drawable-port-xhdpi-screen.png │ │ │ ├── drawable-port-xxhdpi-screen.png │ │ │ └── drawable-port-xxxhdpi-screen.png │ ├── icon.png │ ├── ios │ │ ├── icon │ │ │ ├── icon-40.png │ │ │ ├── icon-40@2x.png │ │ │ ├── icon-50.png │ │ │ ├── icon-50@2x.png │ │ │ ├── icon-60.png │ │ │ ├── icon-60@2x.png │ │ │ ├── icon-60@3x.png │ │ │ ├── icon-72.png │ │ │ ├── icon-72@2x.png │ │ │ ├── icon-76.png │ │ │ ├── icon-76@2x.png │ │ │ ├── icon-small.png │ │ │ ├── icon-small@2x.png │ │ │ ├── icon-small@3x.png │ │ │ ├── icon.png │ │ │ └── icon@2x.png │ │ ├── icons │ │ │ ├── icon-40.png │ │ │ ├── icon-40@2x.png │ │ │ ├── icon-50.png │ │ │ ├── icon-50@2x.png │ │ │ ├── icon-60.png │ │ │ ├── icon-60@2x.png │ │ │ ├── icon-60@3x.png │ │ │ ├── icon-72.png │ │ │ ├── icon-72@2x.png │ │ │ ├── icon-76.png │ │ │ ├── icon-76@2x.png │ │ │ ├── icon-small.png │ │ │ ├── icon-small@2x.png │ │ │ ├── icon.png │ │ │ └── icon@2x.png │ │ └── splash │ │ │ ├── Default-568h@2x~iphone.png │ │ │ ├── Default-667h.png │ │ │ ├── Default-736h.png │ │ │ ├── Default-Landscape-736h.png │ │ │ ├── Default-Landscape@2x~ipad.png │ │ │ ├── Default-Landscape~ipad.png │ │ │ ├── Default-Portrait@2x~ipad.png │ │ │ ├── Default-Portrait~ipad.png │ │ │ ├── Default@2x~iphone.png │ │ │ └── Default~iphone.png │ └── splash.png ├── temp.js └── test │ └── .jshintrc ├── server ├── README.md ├── api │ ├── controllers │ │ ├── README.md │ │ └── posts.js │ ├── mocks │ │ ├── README.md │ │ └── post.json │ ├── models │ │ └── post.js │ └── swagger │ │ └── swagger.yaml ├── conf.docstrap.json ├── conf.json ├── config │ ├── README.md │ └── default.yaml ├── helpers │ ├── README.md │ ├── asset.js │ ├── author.js │ ├── body_class.js │ ├── content.js │ ├── date.js │ ├── encode.js │ ├── excerpt.js │ ├── foreach.js │ ├── ghost_foot.js │ ├── ghost_head.js │ ├── has.js │ ├── image.js │ ├── index.js │ ├── meta_description.js │ ├── meta_title.js │ ├── navigation.js │ ├── post_class.js │ ├── tags.js │ ├── template.js │ ├── title.js │ └── url.js ├── middleware │ └── index.js ├── package.json ├── public │ └── images │ │ └── favicon.ico ├── server.js ├── test │ └── api │ │ ├── controllers │ │ ├── README.md │ │ └── hello_world.js │ │ └── helpers │ │ └── README.md └── utils │ └── http-status-codes.js └── shared ├── favicon.ico ├── img ├── user-cover.png └── user-image.png ├── private-robots.txt ├── robots.txt └── sitemap.xsl /.gitignore: -------------------------------------------------------------------------------- 1 | b-cov 2 | *.seed 3 | *.log 4 | *.csv 5 | *.dat 6 | *.out 7 | *.pid 8 | *.gz 9 | 10 | pids 11 | logs 12 | results 13 | 14 | npm-debug.log 15 | node_modules 16 | out 17 | bower_components 18 | .bowerrc 19 | .idea/* 20 | *.iml 21 | *.sublime-* 22 | projectFilesBackup 23 | 24 | .DS_Store 25 | 26 | # Vardyger DB file 27 | 28 | .build 29 | .dist 30 | .tmp 31 | 32 | # Test generated files 33 | 34 | # Built asset files 35 | 36 | # Coverage reports 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 The Vardyger Foundation 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The Vardyger publishing platform :) 2 | 3 | ## The Admin UI 4 | 5 | 1. View the Admin UI: 6 | 7 |
grunt serve (in the project's /core/client directory)
8 | 9 | ![Admin UI Welcome EN screenshot](https://github.com/Robinyo/Vardyger/blob/master/content/assets/vardyger-admin-ui-welcome-en.png) 10 | 11 | ![Admin UI Welcome DE screenshot](https://github.com/Robinyo/Vardyger/blob/master/content/assets/vardyger-admin-ui-welcome-de.png) 12 | 13 | ![Admin UI Content screenshot](https://github.com/Robinyo/Vardyger/blob/master/content/assets/vardyger-admin-ui-content.png) 14 | 15 | ![Admin UI Preview screenshot](https://github.com/Robinyo/Vardyger/blob/master/content/assets/vardyger-admin-ui-preview.png) 16 | 17 | ![Admin UI Editor screenshot](https://github.com/Robinyo/Vardyger/blob/master/content/assets/vardyger-admin-ui-editor-markdown.png) 18 | 19 | ![Admin UI Editor screenshot](https://github.com/Robinyo/Vardyger/blob/master/content/assets/vardyger-admin-ui-editor-preview.png) 20 | 21 | ## The Vardyger Server 22 | 23 | A sample post rendered via Handlebars with Ghost theme support: 24 | 25 | ![Vardyger post screenshot](https://github.com/Robinyo/Vardyger/blob/master/content/assets/vardyger-post.png) 26 | 27 | For example: 28 | 29 | curl http://localhost:10010/v1/posts/{id} --header "Accept: text/html" 30 | 31 | ## The RESTful API 32 | 33 | ![Swagger UI screenshot](https://github.com/Robinyo/Vardyger/blob/master/content/assets/vardyger-api.png) 34 | 35 | Modelled using Swagger 2.0 and the Swagger Editor, built using Express.js 4.0, Swagger Tools, Mongoose and MongoDB. 36 | 37 | ## Developer Install 38 | 39 | ### Install MongoDB 40 | 41 | 1. Install MongoDB 42 | 43 |
brew update
44 |     brew install mongodb
45 | 46 | ### Install Node.js 47 | 48 | 1. Install Node.js 49 | 50 |
brew install node
51 | 52 | 2. Install Swagger 53 | 54 |
npm install -g swagger
55 | 56 | 3. Clone the repo 57 | 58 |
https://github.com/Robinyo/Vardyger.git
59 | 60 | 4. Install the project's dependencies (as per /core/server/package.json) 61 | 62 |
npm init
63 | 64 | 4. Run MongoDB 65 | 66 |
ulimit -n 1024 && mongod --config /usr/local/etc/mongod.conf
67 | 68 | 6. Start the API server (in the project's /core/server directory) 69 | 70 |
swagger project start
71 | 72 | 7. View the Swagger UI: 73 | 74 |
http://localhost:10010/docs
75 | 76 | **Note:** Edit the API (/core/server/api/swagger/swagger.yaml): 77 | 78 | swagger project edit 79 | 80 | ![Swagger Editor screenshot](https://github.com/Robinyo/Vardyger/blob/master/content/assets/swagger-editor.png) 81 | 82 | #### Copyright & License 83 | 84 | Copyright (c) 2015-2017 The Vardyger Foundation - Released under the MIT license. 85 | -------------------------------------------------------------------------------- /content/README.md: -------------------------------------------------------------------------------- 1 | Place your themes in the themes directory. -------------------------------------------------------------------------------- /content/assets/swagger-editor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/content/assets/swagger-editor.png -------------------------------------------------------------------------------- /content/assets/vardyger-admin-ui-content.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/content/assets/vardyger-admin-ui-content.png -------------------------------------------------------------------------------- /content/assets/vardyger-admin-ui-editor-markdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/content/assets/vardyger-admin-ui-editor-markdown.png -------------------------------------------------------------------------------- /content/assets/vardyger-admin-ui-editor-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/content/assets/vardyger-admin-ui-editor-preview.png -------------------------------------------------------------------------------- /content/assets/vardyger-admin-ui-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/content/assets/vardyger-admin-ui-preview.png -------------------------------------------------------------------------------- /content/assets/vardyger-admin-ui-side-menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/content/assets/vardyger-admin-ui-side-menu.png -------------------------------------------------------------------------------- /content/assets/vardyger-admin-ui-welcome-de.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/content/assets/vardyger-admin-ui-welcome-de.png -------------------------------------------------------------------------------- /content/assets/vardyger-admin-ui-welcome-en.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/content/assets/vardyger-admin-ui-welcome-en.png -------------------------------------------------------------------------------- /content/assets/vardyger-api.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/content/assets/vardyger-api.png -------------------------------------------------------------------------------- /content/assets/vardyger-post.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/content/assets/vardyger-post.png -------------------------------------------------------------------------------- /content/themes/README.md: -------------------------------------------------------------------------------- 1 | Place your themes in this directory. -------------------------------------------------------------------------------- /content/themes/casper/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013-2015 Ghost Foundation 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /content/themes/casper/README.md: -------------------------------------------------------------------------------- 1 | # Casper 2 | 3 | The default theme for [Ghost](http://github.com/tryghost/ghost/). 4 | 5 | To download, visit the [releases](https://github.com/TryGhost/Casper/releases) page. 6 | 7 | ## Copyright & License 8 | 9 | Copyright (c) 2013-2015 Ghost Foundation - Released under the MIT License. 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | -------------------------------------------------------------------------------- /content/themes/casper/assets/fonts/casper-icons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/content/themes/casper/assets/fonts/casper-icons.eot -------------------------------------------------------------------------------- /content/themes/casper/assets/fonts/casper-icons.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Generated by IcoMoon 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /content/themes/casper/assets/fonts/casper-icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/content/themes/casper/assets/fonts/casper-icons.ttf -------------------------------------------------------------------------------- /content/themes/casper/assets/fonts/casper-icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/content/themes/casper/assets/fonts/casper-icons.woff -------------------------------------------------------------------------------- /content/themes/casper/assets/js/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Main JS file for Casper behaviours 3 | */ 4 | 5 | /* globals jQuery, document */ 6 | (function ($, undefined) { 7 | "use strict"; 8 | 9 | var $document = $(document); 10 | 11 | $document.ready(function () { 12 | 13 | var $postContent = $(".post-content"); 14 | $postContent.fitVids(); 15 | 16 | $(".scroll-down").arctic_scroll(); 17 | 18 | $(".menu-button, .nav-cover, .nav-close").on("click", function(e){ 19 | e.preventDefault(); 20 | $("body").toggleClass("nav-opened nav-closed"); 21 | }); 22 | 23 | }); 24 | 25 | // Arctic Scroll by Paul Adam Davis 26 | // https://github.com/PaulAdamDavis/Arctic-Scroll 27 | $.fn.arctic_scroll = function (options) { 28 | 29 | var defaults = { 30 | elem: $(this), 31 | speed: 500 32 | }, 33 | 34 | allOptions = $.extend(defaults, options); 35 | 36 | allOptions.elem.click(function (event) { 37 | event.preventDefault(); 38 | var $this = $(this), 39 | $htmlBody = $('html, body'), 40 | offset = ($this.attr('data-offset')) ? $this.attr('data-offset') : false, 41 | position = ($this.attr('data-position')) ? $this.attr('data-position') : false, 42 | toMove; 43 | 44 | if (offset) { 45 | toMove = parseInt(offset); 46 | $htmlBody.stop(true, false).animate({scrollTop: ($(this.hash).offset().top + toMove) }, allOptions.speed); 47 | } else if (position) { 48 | toMove = parseInt(position); 49 | $htmlBody.stop(true, false).animate({scrollTop: toMove }, allOptions.speed); 50 | } else { 51 | $htmlBody.stop(true, false).animate({scrollTop: ($(this.hash).offset().top) }, allOptions.speed); 52 | } 53 | }); 54 | 55 | }; 56 | })(jQuery); 57 | -------------------------------------------------------------------------------- /content/themes/casper/assets/js/jquery.fitvids.js: -------------------------------------------------------------------------------- 1 | /*global jQuery */ 2 | /*jshint browser:true */ 3 | /*! 4 | * FitVids 1.1 5 | * 6 | * Copyright 2013, Chris Coyier - http://css-tricks.com + Dave Rupert - http://daverupert.com 7 | * Credit to Thierry Koblentz - http://www.alistapart.com/articles/creating-intrinsic-ratios-for-video/ 8 | * Released under the WTFPL license - http://sam.zoy.org/wtfpl/ 9 | * 10 | */ 11 | 12 | (function( $ ){ 13 | 14 | "use strict"; 15 | 16 | $.fn.fitVids = function( options ) { 17 | var settings = { 18 | customSelector: null 19 | }; 20 | 21 | if(!document.getElementById('fit-vids-style')) { 22 | // appendStyles: https://github.com/toddmotto/fluidvids/blob/master/dist/fluidvids.js 23 | var head = document.head || document.getElementsByTagName('head')[0]; 24 | var css = '.fluid-width-video-wrapper{width:100%;position:relative;padding:0;}.fluid-width-video-wrapper iframe,.fluid-width-video-wrapper object,.fluid-width-video-wrapper embed {position:absolute;top:0;left:0;width:100%;height:100%;}'; 25 | var div = document.createElement('div'); 26 | div.innerHTML = '

x

'; 27 | head.appendChild(div.childNodes[1]); 28 | } 29 | 30 | if ( options ) { 31 | $.extend( settings, options ); 32 | } 33 | 34 | return this.each(function(){ 35 | var selectors = [ 36 | "iframe[src*='player.vimeo.com']", 37 | "iframe[src*='youtube.com']", 38 | "iframe[src*='youtube-nocookie.com']", 39 | "iframe[src*='kickstarter.com'][src*='video.html']", 40 | "object", 41 | "embed" 42 | ]; 43 | 44 | if (settings.customSelector) { 45 | selectors.push(settings.customSelector); 46 | } 47 | 48 | var $allVideos = $(this).find(selectors.join(',')); 49 | $allVideos = $allVideos.not("object object"); // SwfObj conflict patch 50 | 51 | $allVideos.each(function(){ 52 | var $this = $(this); 53 | if (this.tagName.toLowerCase() === 'embed' && $this.parent('object').length || $this.parent('.fluid-width-video-wrapper').length) { return; } 54 | var height = ( this.tagName.toLowerCase() === 'object' || ($this.attr('height') && !isNaN(parseInt($this.attr('height'), 10))) ) ? parseInt($this.attr('height'), 10) : $this.height(), 55 | width = !isNaN(parseInt($this.attr('width'), 10)) ? parseInt($this.attr('width'), 10) : $this.width(), 56 | aspectRatio = height / width; 57 | if(!$this.attr('id')){ 58 | var videoID = 'fitvid' + Math.floor(Math.random()*999999); 59 | $this.attr('id', videoID); 60 | } 61 | $this.wrap('
').parent('.fluid-width-video-wrapper').css('padding-top', (aspectRatio * 100)+"%"); 62 | $this.removeAttr('height').removeAttr('width'); 63 | }); 64 | }); 65 | }; 66 | // Works with either jQuery or Zepto 67 | })( window.jQuery || window.Zepto ); 68 | -------------------------------------------------------------------------------- /content/themes/casper/author.hbs: -------------------------------------------------------------------------------- 1 | {{!< default}} 2 | {{! The tag above means - insert everything in this file into the {body} of the default.hbs template }} 3 | 4 | {{! The big featured header }} 5 | 6 | {{! Everything inside the #author tags pulls data from the author }} 7 | {{#author}} 8 |
9 | 15 |
16 | 17 |
18 | {{#if image}} 19 |
20 |
21 |
22 | {{/if}} 23 |

{{name}}

24 | {{#if bio}} 25 |

{{bio}}

26 | {{/if}} 27 |
28 | {{#if location}}{{location}}{{/if}} 29 | {{#if website}}{{website}}{{/if}} 30 | {{plural ../pagination.total empty='No posts' singular='% post' plural='% posts'}} 31 |
32 |
33 | {{/author}} 34 | 35 | {{! The main content area on the homepage }} 36 |
37 | 38 | {{! The tag below includes the post loop - partials/loop.hbs }} 39 | {{> "loop"}} 40 | 41 |
42 | -------------------------------------------------------------------------------- /content/themes/casper/default.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{! Document Settings }} 5 | 6 | 7 | 8 | {{! Page Meta }} 9 | {{meta_title}} 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | {{! Styles'n'Scripts }} 18 | 19 | 20 | 21 | {{! Ghost outputs important style and meta data with this tag }} 22 | {{ghost_head}} 23 | 24 | 25 | 26 | {{! navigation}} 27 | 28 | 39 | 40 | 41 |
42 | 43 | {{! Everything else gets inserted here }} 44 | {{{body}}} 45 | 46 | 50 | 51 |
52 | 53 | {{! Ghost outputs important scripts and data with this tag }} 54 | {{ghost_foot}} 55 | 56 | {{! The main JavaScript file for Casper }} 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /content/themes/casper/index.hbs: -------------------------------------------------------------------------------- 1 | {{!< default}} 2 | {{! The tag above means - insert everything in this file into the {body} of the default.hbs template }} 3 | 4 | {{! The big featured header }} 5 |
6 | 12 |
13 |
14 |

{{@blog.title}}

15 |

{{@blog.description}}

16 |
17 |
18 | 19 |
20 | 21 | {{! The main content area on the homepage }} 22 |
23 | 24 | {{! The tag below includes the post loop - partials/loop.hbs }} 25 | {{> "loop"}} 26 | 27 |
28 | -------------------------------------------------------------------------------- /content/themes/casper/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Casper", 3 | "version": "1.2.4" 4 | } 5 | -------------------------------------------------------------------------------- /content/themes/casper/page.hbs: -------------------------------------------------------------------------------- 1 | {{!< default}} 2 | 3 | {{! This is a page template. A page outputs content just like any other post, and has all the same 4 | attributes by default, but you can also customise it to behave differently if you prefer. }} 5 | 6 | {{! Everything inside the #post tags pulls data from the page }} 7 | {{#post}} 8 | 9 |
10 | 16 |
17 | 18 |
19 |
20 | 21 |
22 |

{{title}}

23 |
24 | 25 |
26 | {{content}} 27 |
28 | 29 |
30 |
31 | {{/post}} 32 | -------------------------------------------------------------------------------- /content/themes/casper/partials/loop.hbs: -------------------------------------------------------------------------------- 1 | {{! Previous/next page links - only displayed on page 2+ }} 2 |
3 | {{pagination}} 4 |
5 | 6 | {{! This is the post loop - each post will be output using this markup }} 7 | {{#foreach posts}} 8 |
9 |
10 |

{{{title}}}

11 |
12 |
13 |

{{excerpt words="26"}} »

14 |
15 | 21 |
22 | {{/foreach}} 23 | 24 | {{! Previous/next page links - displayed on every page }} 25 | {{pagination}} 26 | -------------------------------------------------------------------------------- /content/themes/casper/partials/navigation.hbs: -------------------------------------------------------------------------------- 1 | 13 | 14 | -------------------------------------------------------------------------------- /content/themes/casper/post.hbs: -------------------------------------------------------------------------------- 1 | {{!< default}} 2 | 3 | {{! The comment above "< default" means - insert everything in this file into 4 | the {body} of the default.hbs template, which contains our header/footer. }} 5 | 6 | {{! Everything inside the #post tags pulls data from the post }} 7 | {{#post}} 8 | 9 |
10 | 16 |
17 | 18 |
19 |
20 | 21 |
22 |

{{title}}

23 | 26 |
27 | 28 |
29 | {{content}} 30 |
31 | 32 | 61 | 62 |
63 |
64 | 65 | {{/post}} 66 | -------------------------------------------------------------------------------- /content/themes/casper/tag.hbs: -------------------------------------------------------------------------------- 1 | {{!< default}} 2 | {{! The tag above means - insert everything in this file into the {body} of the default.hbs template }} 3 | 4 | {{! If we have a tag cover, display that - else blog cover - else nothing }} 5 |
6 | 12 |
13 |
14 |

{{tag.name}}

15 |

16 | {{#if tag.description}} 17 | {{tag.description}} 18 | {{else}} 19 | A {{pagination.total}}-post collection 20 | {{/if}} 21 |

22 |
23 |
24 |
25 | 26 | {{! The main content area on the homepage }} 27 |
28 | 29 | {{! The tag below includes the post loop - partials/loop.hbs }} 30 | {{> "loop"}} 31 | 32 |
33 | -------------------------------------------------------------------------------- /core/README.md: -------------------------------------------------------------------------------- 1 | The directory structure: 2 | 3 | * client 4 | * server 5 | * shared -------------------------------------------------------------------------------- /core/client/.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /core/client/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | www 3 | .idea 4 | .temp 5 | .sass-cache 6 | app/bower_components 7 | coverage 8 | platforms 9 | plugins 10 | *.swp 11 | *.swo 12 | *.log 13 | *.DS_Store 14 | -------------------------------------------------------------------------------- /core/client/.jshintignore: -------------------------------------------------------------------------------- 1 | app/scripts/config.js 2 | -------------------------------------------------------------------------------- /core/client/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "browser": true, 4 | "esnext": true, 5 | "bitwise": true, 6 | "camelcase": true, 7 | "curly": true, 8 | "eqeqeq": true, 9 | "immed": true, 10 | "indent": 2, 11 | "latedef": true, 12 | "newcap": true, 13 | "noarg": true, 14 | "quotmark": "single", 15 | "regexp": true, 16 | "undef": true, 17 | "unused": true, 18 | "strict": true, 19 | "trailing": true, 20 | "smarttabs": true, 21 | "globals": { 22 | "angular": false, 23 | "cordova": false, 24 | "StatusBar": false 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /core/client/Gruntfile.js: -------------------------------------------------------------------------------- 1 | // Generated on 2015-07-06 using generator-ionic 0.7.3 2 | 'use strict'; 3 | 4 | var _ = require('lodash'); 5 | var path = require('path'); 6 | var cordovaCli = require('cordova'); 7 | var spawn = process.platform === 'win32' ? require('win-spawn') : require('child_process').spawn; 8 | 9 | module.exports = function (grunt) { 10 | 11 | // Load grunt tasks automatically 12 | require('load-grunt-tasks')(grunt); 13 | 14 | // Time how long tasks take. Can help when optimizing build times 15 | require('time-grunt')(grunt); 16 | 17 | // Define the configuration for all the tasks 18 | grunt.initConfig({ 19 | 20 | // Project settings 21 | yeoman: { 22 | // configurable paths 23 | app: 'app', 24 | scripts: 'scripts', 25 | styles: 'styles', 26 | images: 'images', 27 | test: 'test', 28 | dist: 'www' 29 | }, 30 | 31 | /* 32 | 33 | // Environment Variables for Angular App 34 | // This creates an Angular Module that can be injected via ENV 35 | // Add any desired constants to the ENV objects below. 36 | // https://github.com/diegonetto/generator-ionic/blob/master/docs/FAQ.md#how-do-i-add-constants 37 | ngconstant: { 38 | options: { 39 | space: ' ', 40 | wrap: '"use strict";\n\n {%= __ngModule %}', 41 | name: 'config', 42 | dest: '<%= yeoman.app %>/<%= yeoman.scripts %>/configuration.js' 43 | }, 44 | development: { 45 | constants: { 46 | ENV: { 47 | name: 'development', 48 | apiEndpoint: 'http://dev.yoursite.com:10000/' 49 | } 50 | } 51 | }, 52 | production: { 53 | constants: { 54 | ENV: { 55 | name: 'production', 56 | apiEndpoint: 'http://api.yoursite.com/' 57 | } 58 | } 59 | } 60 | }, 61 | 62 | */ 63 | 64 | // Watches files for changes and runs tasks based on the changed files 65 | watch: { 66 | bower: { 67 | files: ['bower.json'], 68 | tasks: ['wiredep', 'newer:copy:app'] 69 | }, 70 | html: { 71 | files: ['<%= yeoman.app %>/**/*.html'], 72 | tasks: ['newer:copy:app'] 73 | }, 74 | js: { 75 | files: ['<%= yeoman.app %>/<%= yeoman.scripts %>/**/*.js'], 76 | tasks: ['newer:copy:app', 'newer:jshint:all'] 77 | }, 78 | compass: { 79 | // files: ['<%= yeoman.app %>/<%= yeoman.styles %>/**/*.{scss,sass}'], 80 | files: ['<%= yeoman.app %>/<%= yeoman.styles %>/main.scss'], 81 | tasks: ['compass:server', 'autoprefixer', 'newer:copy:tmp'] 82 | } 83 | 84 | /* 85 | 86 | gruntfile: { 87 | files: ['Gruntfile.js'], 88 | tasks: ['ngconstant:development', 'newer:copy:app'] 89 | } 90 | 91 | */ 92 | }, 93 | 94 | // The actual grunt server settings 95 | connect: { 96 | options: { 97 | port: 9000, 98 | // Change this to '0.0.0.0' to access the server from outside. 99 | hostname: 'localhost' 100 | }, 101 | dist: { 102 | options: { 103 | base: '<%= yeoman.dist %>' 104 | } 105 | }, 106 | coverage: { 107 | options: { 108 | port: 9002, 109 | open: true, 110 | base: ['coverage'] 111 | } 112 | } 113 | }, 114 | 115 | // Make sure code styles are up to par and there are no obvious mistakes 116 | jshint: { 117 | options: { 118 | jshintrc: '.jshintrc', 119 | reporter: require('jshint-stylish') 120 | }, 121 | all: [ 122 | 'Gruntfile.js', 123 | '<%= yeoman.app %>/<%= yeoman.scripts %>/**/*.js' 124 | ], 125 | test: { 126 | options: { 127 | jshintrc: 'test/.jshintrc' 128 | }, 129 | src: ['test/unit/**/*.js'] 130 | } 131 | }, 132 | 133 | // Empties folders to start fresh 134 | clean: { 135 | dist: { 136 | files: [{ 137 | dot: true, 138 | src: [ 139 | '.temp', 140 | '<%= yeoman.dist %>/*', 141 | '!<%= yeoman.dist %>/.git*' 142 | ] 143 | }] 144 | }, 145 | server: '.temp' 146 | }, 147 | 148 | autoprefixer: { 149 | options: { 150 | browsers: ['last 1 version'] 151 | }, 152 | dist: { 153 | files: [{ 154 | expand: true, 155 | cwd: '.temp/<%= yeoman.styles %>/', 156 | src: '{,*/}*.css', 157 | dest: '.temp/<%= yeoman.styles %>/' 158 | }] 159 | } 160 | }, 161 | 162 | // Automatically inject Bower components into the app 163 | wiredep: { 164 | app: { 165 | src: ['<%= yeoman.app %>/index.html'], 166 | ignorePath: /\.\.\// 167 | }, 168 | sass: { 169 | src: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'], 170 | ignorePath: /(\.\.\/){1,2}bower_components\// 171 | } 172 | }, 173 | 174 | // Compiles Sass to CSS and generates necessary files if requested 175 | compass: { 176 | options: { 177 | sassDir: '<%= yeoman.app %>/<%= yeoman.styles %>', 178 | cssDir: '.temp/<%= yeoman.styles %>', 179 | generatedImagesDir: '.temp/<%= yeoman.images %>/generated', 180 | imagesDir: '<%= yeoman.app %>/<%= yeoman.images %>', 181 | javascriptsDir: '<%= yeoman.app %>/<%= yeoman.scripts %>', 182 | fontsDir: '<%= yeoman.app %>/<%= yeoman.styles %>/fonts', 183 | importPath: '<%= yeoman.app %>/bower_components', 184 | httpImagesPath: '/<%= yeoman.images %>', 185 | httpGeneratedImagesPath: '/<%= yeoman.images %>/generated', 186 | httpFontsPath: '/<%= yeoman.styles %>/fonts', 187 | relativeAssets: false, 188 | assetCacheBuster: false, 189 | raw: 'Sass::Script::Number.precision = 10\n' 190 | }, 191 | dist: { 192 | options: { 193 | generatedImagesDir: '<%= yeoman.dist %>/<%= yeoman.images %>/generated' 194 | } 195 | }, 196 | server: { 197 | options: { 198 | debugInfo: true 199 | } 200 | } 201 | }, 202 | 203 | 204 | // Reads HTML for usemin blocks to enable smart builds that automatically 205 | // concat, minify and revision files. Creates configurations in memory so 206 | // additional tasks can operate on them 207 | useminPrepare: { 208 | html: '<%= yeoman.app %>/index.html', 209 | options: { 210 | dest: '<%= yeoman.dist %>', 211 | staging: '.temp', 212 | flow: { 213 | html: { 214 | steps: { 215 | js: ['concat', 'uglifyjs'], 216 | css: ['cssmin'] 217 | }, 218 | post: {} 219 | } 220 | } 221 | } 222 | }, 223 | 224 | // Performs rewrites based on the useminPrepare configuration 225 | usemin: { 226 | html: ['<%= yeoman.dist %>/**/*.html'], 227 | css: ['<%= yeoman.dist %>/<%= yeoman.styles %>/**/*.css'], 228 | options: { 229 | assetsDirs: ['<%= yeoman.dist %>'] 230 | } 231 | }, 232 | 233 | // The following *-min tasks produce minified files in the dist folder 234 | cssmin: { 235 | options: { 236 | //root: '<%= yeoman.app %>', 237 | noRebase: true 238 | } 239 | }, 240 | htmlmin: { 241 | dist: { 242 | options: { 243 | collapseWhitespace: true, 244 | collapseBooleanAttributes: true, 245 | removeCommentsFromCDATA: true, 246 | removeOptionalTags: true 247 | }, 248 | files: [{ 249 | expand: true, 250 | cwd: '<%= yeoman.dist %>', 251 | src: ['*.html', 'templates/**/*.html'], 252 | dest: '<%= yeoman.dist %>' 253 | }] 254 | } 255 | }, 256 | 257 | // Copies remaining files to places other tasks can use 258 | copy: { 259 | dist: { 260 | files: [{ 261 | expand: true, 262 | dot: true, 263 | cwd: '<%= yeoman.app %>', 264 | dest: '<%= yeoman.dist %>', 265 | src: [ 266 | '<%= yeoman.images %>/**/*.{png,jpg,jpeg,gif,webp,svg}', 267 | '*.html', 268 | 'templates/**/*.html', 269 | 'fonts/*' 270 | ] 271 | }, { 272 | expand: true, 273 | cwd: '.temp/<%= yeoman.images %>', 274 | dest: '<%= yeoman.dist %>/<%= yeoman.images %>', 275 | src: ['generated/*'] 276 | }] 277 | }, 278 | styles: { 279 | expand: true, 280 | cwd: '<%= yeoman.app %>/<%= yeoman.styles %>', 281 | dest: '.temp/<%= yeoman.styles %>/', 282 | src: '{,*/}*.css' 283 | }, 284 | fonts: { 285 | expand: true, 286 | cwd: 'app/bower_components/ionic/release/fonts/', 287 | dest: '<%= yeoman.app %>/fonts/', 288 | src: '*' 289 | }, 290 | vendor: { 291 | expand: true, 292 | cwd: '<%= yeoman.app %>/vendor', 293 | dest: '.temp/<%= yeoman.styles %>/', 294 | src: '{,*/}*.css' 295 | }, 296 | app: { 297 | expand: true, 298 | cwd: '<%= yeoman.app %>', 299 | dest: '<%= yeoman.dist %>/', 300 | src: [ 301 | '**/*', 302 | '!**/*.(scss,sass,css)', 303 | ] 304 | }, 305 | tmp: { 306 | expand: true, 307 | cwd: '.temp', 308 | dest: '<%= yeoman.dist %>/', 309 | src: '**/*' 310 | } 311 | }, 312 | 313 | concurrent: { 314 | ionic: { 315 | tasks: [], 316 | options: { 317 | logConcurrentOutput: true 318 | } 319 | }, 320 | server: [ 321 | 'compass:server', 322 | 'copy:styles', 323 | 'copy:vendor', 324 | 'copy:fonts' 325 | ], 326 | test: [ 327 | 'compass', 328 | 'copy:styles', 329 | 'copy:vendor', 330 | 'copy:fonts' 331 | ], 332 | dist: [ 333 | 'compass:dist', 334 | 'copy:styles', 335 | 'copy:vendor', 336 | 'copy:fonts' 337 | ] 338 | }, 339 | 340 | // By default, your `index.html`'s will take care of 341 | // minification. These next options are pre-configured if you do not wish 342 | // to use the Usemin blocks. 343 | // cssmin: { 344 | // dist: { 345 | // files: { 346 | // '<%= yeoman.dist %>/<%= yeoman.styles %>/main.css': [ 347 | // '.temp/<%= yeoman.styles %>/**/*.css', 348 | // '<%= yeoman.app %>/<%= yeoman.styles %>/**/*.css' 349 | // ] 350 | // } 351 | // } 352 | // }, 353 | // uglify: { 354 | // dist: { 355 | // files: { 356 | // '<%= yeoman.dist %>/<%= yeoman.scripts %>/scripts.js': [ 357 | // '<%= yeoman.dist %>/<%= yeoman.scripts %>/scripts.js' 358 | // ] 359 | // } 360 | // } 361 | // }, 362 | // concat: { 363 | // dist: {} 364 | // }, 365 | 366 | // ngAnnotate tries to make the code safe for minification automatically by 367 | // using the Angular long form for dependency injection. 368 | ngAnnotate: { 369 | dist: { 370 | files: [{ 371 | expand: true, 372 | cwd: '.temp/concat/<%= yeoman.scripts %>', 373 | src: '*.js', 374 | dest: '.temp/concat/<%= yeoman.scripts %>' 375 | }] 376 | } 377 | } 378 | 379 | }); 380 | 381 | // Register tasks for all Cordova commands 382 | _.functions(cordovaCli).forEach(function (name) { 383 | grunt.registerTask(name, function () { 384 | this.args.unshift(name.replace('cordova:', '')); 385 | // Handle URL's being split up by Grunt because of `:` characters 386 | if (_.contains(this.args, 'http') || _.contains(this.args, 'https')) { 387 | this.args = this.args.slice(0, -2).concat(_.last(this.args, 2).join(':')); 388 | } 389 | var done = this.async(); 390 | var exec = process.platform === 'win32' ? 'cordova.cmd' : 'cordova'; 391 | var cmd = path.resolve('./node_modules/cordova/bin', exec); 392 | var flags = process.argv.splice(3); 393 | var child = spawn(cmd, this.args.concat(flags)); 394 | child.stdout.on('data', function (data) { 395 | grunt.log.writeln(data); 396 | }); 397 | child.stderr.on('data', function (data) { 398 | grunt.log.error(data); 399 | }); 400 | child.on('close', function (code) { 401 | code = code ? false : true; 402 | done(code); 403 | }); 404 | }); 405 | }); 406 | 407 | // Since Apache Ripple serves assets directly out of their respective platform 408 | // directories, we watch all registered files and then copy all un-built assets 409 | // over to <%= yeoman.dist %>/. Last step is running cordova prepare so we can refresh the ripple 410 | // browser tab to see the changes. Technically ripple runs `cordova prepare` on browser 411 | // refreshes, but at this time you would need to re-run the emulator to see changes. 412 | grunt.registerTask('ripple', ['wiredep', 'newer:copy:app', 'ripple-emulator']); 413 | grunt.registerTask('ripple-emulator', function () { 414 | grunt.config.set('watch', { 415 | all: { 416 | files: _.flatten(_.pluck(grunt.config.get('watch'), 'files')), 417 | tasks: ['newer:copy:app', 'prepare'] 418 | } 419 | }); 420 | 421 | var cmd = path.resolve('./node_modules/ripple-emulator/bin', 'ripple'); 422 | var child = spawn(cmd, ['emulate']); 423 | child.stdout.on('data', function (data) { 424 | grunt.log.writeln(data); 425 | }); 426 | child.stderr.on('data', function (data) { 427 | grunt.log.error(data); 428 | }); 429 | process.on('exit', function (code) { 430 | child.kill('SIGINT'); 431 | process.exit(code); 432 | }); 433 | 434 | return grunt.task.run(['watch']); 435 | }); 436 | 437 | // Dynamically configure `karma` target of `watch` task so that 438 | // we don't have to run the karma test server as part of `grunt serve` 439 | grunt.registerTask('watch:karma', function () { 440 | var karma = { 441 | files: ['<%= yeoman.app %>/<%= yeoman.scripts %>/**/*.js', '<%= yeoman.test %>/spec/**/*.js'], 442 | tasks: ['newer:jshint:test', 'karma:unit:run'] 443 | }; 444 | grunt.config.set('watch', karma); 445 | return grunt.task.run(['watch']); 446 | }); 447 | 448 | // Wrap ionic-cli commands 449 | grunt.registerTask('ionic', function() { 450 | var done = this.async(); 451 | var script = path.resolve('./node_modules/ionic/bin/', 'ionic'); 452 | var flags = process.argv.splice(3); 453 | var child = spawn(script, this.args.concat(flags), { stdio: 'inherit' }); 454 | child.on('close', function (code) { 455 | code = code ? false : true; 456 | done(code); 457 | }); 458 | }); 459 | 460 | grunt.registerTask('test', [ 461 | 'wiredep', 462 | 'clean', 463 | 'concurrent:test', 464 | 'autoprefixer', 465 | 'karma:unit:start', 466 | 'watch:karma' 467 | ]); 468 | 469 | grunt.registerTask('serve', function (target) { 470 | if (target === 'compress') { 471 | return grunt.task.run(['compress', 'ionic:serve']); 472 | } 473 | 474 | grunt.config('concurrent.ionic.tasks', ['ionic:serve', 'watch']); 475 | grunt.task.run(['wiredep', 'init', 'concurrent:ionic']); 476 | }); 477 | grunt.registerTask('emulate', function() { 478 | grunt.config('concurrent.ionic.tasks', ['ionic:emulate:' + this.args.join(), 'watch']); 479 | return grunt.task.run(['init', 'concurrent:ionic']); 480 | }); 481 | grunt.registerTask('run', function() { 482 | grunt.config('concurrent.ionic.tasks', ['ionic:run:' + this.args.join(), 'watch']); 483 | return grunt.task.run(['init', 'concurrent:ionic']); 484 | }); 485 | grunt.registerTask('build', function() { 486 | return grunt.task.run(['init', 'ionic:build:' + this.args.join()]); 487 | }); 488 | 489 | grunt.registerTask('init', [ 490 | 'clean', 491 | // 'ngconstant:development', 492 | 'wiredep', 493 | 'concurrent:server', 494 | 'autoprefixer', 495 | 'newer:copy:app', 496 | 'newer:copy:tmp' 497 | ]); 498 | 499 | 500 | grunt.registerTask('compress', [ 501 | 'clean', 502 | // 'ngconstant:production', 503 | 'wiredep', 504 | 'useminPrepare', 505 | 'concurrent:dist', 506 | 'autoprefixer', 507 | 'concat', 508 | 'ngAnnotate', 509 | 'copy:dist', 510 | 'cssmin', 511 | 'uglify', 512 | 'usemin', 513 | 'htmlmin' 514 | ]); 515 | 516 | grunt.registerTask('coverage', 517 | ['karma:continuous', 518 | 'connect:coverage:keepalive' 519 | ]); 520 | 521 | grunt.registerTask('default', [ 522 | 'wiredep', 523 | 'newer:jshint', 524 | // 'karma:continuous', 525 | 'compress' 526 | ]); 527 | }; 528 | -------------------------------------------------------------------------------- /core/client/app/README.md: -------------------------------------------------------------------------------- 1 | TODO: 2 | -------------------------------------------------------------------------------- /core/client/app/fonts/ionicons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/app/fonts/ionicons.eot -------------------------------------------------------------------------------- /core/client/app/fonts/ionicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/app/fonts/ionicons.ttf -------------------------------------------------------------------------------- /core/client/app/fonts/ionicons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/app/fonts/ionicons.woff -------------------------------------------------------------------------------- /core/client/app/images/ionic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/app/images/ionic.png -------------------------------------------------------------------------------- /core/client/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Vardyger 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 29 | 30 | 31 | 34 | 35 | 36 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /core/client/app/scripts/app.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Vardyger 3 | * Copyright(c) 2015 Rob Ferguson 4 | * MIT Licensed 5 | */ 6 | 7 | 'use strict'; 8 | 9 | // Declare a new module called 'vardyger', and list its dependencies. 10 | angular.module('vardyger', [ 11 | 'ionic', // inject the Ionic framework 12 | 'ionic.contrib.icon', // inject the ionic.contrib.icon module 13 | // 'angular-http-auth', // in bower.json but http-auth-interceptor in http-auth-interceptor.js 14 | 'http-auth-interceptor', // inject the angular-http-auth module 15 | 'LocalStorageModule', // inject the angular-local-storage module 16 | 'ngAnimate', // inject the ngAnimate module 17 | 'ngFx', // inject the ngFx module 18 | 'ngMockE2E', // inject the angular-mocks module 19 | 'pascalprecht.translate' // inject the angular-translate module 20 | ]) 21 | .config(function($ionicConfigProvider, $stateProvider, $urlRouterProvider, $translateProvider) { 22 | 23 | $translateProvider 24 | .useStaticFilesLoader({ 25 | prefix: 'scripts/locales/', 26 | suffix: '.json' 27 | }) 28 | .registerAvailableLanguageKeys(['en', 'de'], { 29 | 'en' : 'en', 'en_GB': 'en', 'en_US': 'en', 30 | 'de' : 'de', 'de_DE': 'de', 'de_CH': 'de' 31 | }) 32 | .preferredLanguage('de') 33 | .fallbackLanguage('de') 34 | .determinePreferredLanguage() 35 | .useSanitizeValueStrategy('escapeParameters'); 36 | 37 | // By default, views are cached to improve performance. 38 | // Set $ionicConfigProvider.views.maxCache(0); to disable cache globally 39 | // See: http://ionicframework.com/docs/api/directive/ionNavView/ 40 | 41 | $ionicConfigProvider.views.maxCache(10); // the default is 10 42 | // $ionicConfigProvider.views.transition('none'); 43 | $ionicConfigProvider.views.transition('platform'); // platform, ios, android, none 44 | $ionicConfigProvider.views.forwardCache(false); // the default is false 45 | $ionicConfigProvider.backButton.icon('ion-ios-arrow-back'); 46 | $ionicConfigProvider.backButton.text(''); // default is 'Back' 47 | $ionicConfigProvider.backButton.previousTitleText(false); // hides the 'Back' text 48 | $ionicConfigProvider.templates.maxPrefetch(20); 49 | 50 | $stateProvider 51 | .state('app', { 52 | url: '/app', 53 | templateUrl: 'templates/side-menu-template.html', 54 | controller: 'AppController', 55 | abstract: true 56 | }) 57 | 58 | .state('app.welcome', { 59 | url: '/welcome', 60 | cache: false, 61 | views: { 62 | 'menuContent': { 63 | templateUrl: 'templates/welcome-template.html' 64 | } 65 | } 66 | }) 67 | 68 | .state('app.main', { 69 | url: '/main', 70 | cache: false, 71 | views: { 72 | 'menuContent': { 73 | templateUrl: 'templates/main-template.html', 74 | controller: 'MainController', 75 | resolve: { 76 | posts: function(PostsService) { 77 | return PostsService.findPosts(); 78 | } 79 | } 80 | } 81 | } 82 | }) 83 | 84 | .state('app.preview', { 85 | url: '/preview/{postId}', 86 | views: { 87 | 'menuContent': { 88 | templateUrl: 'templates/preview-template.html', 89 | controller: 'PreviewController', 90 | resolve: { 91 | post: function($stateParams, PostsService) { 92 | return PostsService.findPostById($stateParams.postId); 93 | } 94 | } 95 | } 96 | } 97 | }) 98 | 99 | .state('app.editor', { 100 | url: '/editor/{postId}', 101 | views: { 102 | 'menuContent': { 103 | templateUrl: 'templates/editor-template.html', 104 | controller: 'EditorController', 105 | resolve: { 106 | post: function($stateParams, PostsService) { 107 | return PostsService.findPostById($stateParams.postId); 108 | } 109 | } 110 | } 111 | } 112 | }); 113 | 114 | // if none of the above states are matched, use this as the fallback 115 | $urlRouterProvider.otherwise('/app/welcome'); 116 | }) 117 | 118 | .run(function($ionicPlatform, $httpBackend, localStorageService) { 119 | 120 | $ionicPlatform.ready(function() { 121 | 122 | // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard 123 | // for form inputs) 124 | if (window.cordova && window.cordova.plugins.Keyboard) { 125 | cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true); 126 | } 127 | 128 | if (window.StatusBar) { 129 | StatusBar.styleDefault(); 130 | } 131 | 132 | }); 133 | 134 | var posts = [ 135 | 136 | { 137 | metaTitle: 'Ionic Style Guide', 138 | metaDescription: 'In a previous post, ...', 139 | post: { 140 | id: '1', 141 | title: 'Ionic Style Guide', 142 | html: '

In a previous post, ...

', 143 | markdown: 'In a previous post, ...' 144 | } 145 | }, 146 | 147 | { 148 | metaTitle: 'Customising Ionic with Sass', 149 | metaDescription: 'In a previous post, ...', 150 | post: { 151 | id: '2', 152 | title: 'Customising Ionic with Sass', 153 | html: '

In a previous post, ...

', 154 | markdown: 'In a previous post, ...' 155 | } 156 | }, 157 | 158 | { 159 | metaTitle: 'Ionic, Angular and Cordova', 160 | metaDescription: 'In a previous post, ...', 161 | post: { 162 | id: '3', 163 | title: 'Ionic, Angular and Cordova', 164 | html: '

In a previous post, ...

', 165 | markdown: 'In a previous post, ...' 166 | } 167 | }, 168 | 169 | { 170 | metaTitle: 'Annotating JavaScript using JSDoc tags', 171 | metaDescription: 'In a previous post, ...', 172 | post: { 173 | id: '4', 174 | title: 'Annotating JavaScript using JSDoc tags', 175 | html: '

In a previous post, ...

', 176 | markdown: 'In a previous post, ...' 177 | } 178 | }, 179 | 180 | { 181 | metaTitle: 'Express, Handlebars and Ghost Themes', 182 | metaDescription: 'In a previous post, ...', 183 | post: { 184 | id: '5', 185 | title: 'Express, Handlebars and Ghost Themes', 186 | html: '

In a previous post, ...

', 187 | markdown: 'In a previous post, ...' 188 | } 189 | }, 190 | 191 | { 192 | metaTitle: 'Swagger, Express, and Content Negotiation', 193 | metaDescription: 'In a previous post, ...', 194 | post: { 195 | id: '6', 196 | title: 'Swagger, Express, and Content Negotiation', 197 | html: '

In a previous post, ...

', 198 | markdown: 'In a previous post, ...' 199 | } 200 | }, 201 | 202 | { 203 | metaTitle: 'The Vardyger publishing platform :)', 204 | metaDescription: 'In a previous post, ...', 205 | post: { 206 | id: '7', 207 | title: 'The Vardyger publishing platform :)', 208 | html: '

In a previous post, ...

', 209 | markdown: 'In a previous post, ...' 210 | } 211 | } 212 | 213 | ]; 214 | 215 | /* jshint ignore:start */ 216 | 217 | // GET /vardyger/api/v1.0/posts or 401 218 | $httpBackend.whenGET('https://posts').respond(function (method, url, data, headers) { 219 | var authToken = localStorageService.get('authorizationToken'); 220 | return authToken ? [200, posts] : [401]; 221 | }); 222 | 223 | $httpBackend.whenPOST('https://login').respond(function(method, url, data) { 224 | var authToken = 'NjMwNjM4OTQtMjE0Mi00ZWYzLWEzMDQtYWYyMjkyMzNiOGIy'; 225 | return [200 , { authorizationToken: authToken } ]; 226 | }); 227 | 228 | $httpBackend.whenPOST('https://logout').respond(function(method, url, data) { 229 | return [200]; 230 | }); 231 | 232 | $httpBackend.whenGET(/.*/).passThrough(); 233 | 234 | /* jshint ignore:end */ 235 | 236 | }); 237 | 238 | 239 | // Code here will be linted with JSHint. 240 | /* jshint ignore:start */ 241 | // Code here will be ignored by JSHint. 242 | /* jshint ignore:end */ 243 | 244 | // You can also ignore a single line with a trailing comment like this: 245 | // ignoreThis(); // jshint ignore:line 246 | 247 | /* 248 | 249 | // .useStorage(); 250 | 251 | */ 252 | -------------------------------------------------------------------------------- /core/client/app/scripts/config/config.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Vardyger 3 | * Copyright(c) 2015 Rob Ferguson 4 | * MIT Licensed 5 | */ 6 | 7 | 'use strict'; 8 | 9 | angular.module('config', []) 10 | .constant('ENV', { 11 | name:'development', 12 | apiEndpoint:'http://dev.yoursite.com:10000/' 13 | }); 14 | 15 | -------------------------------------------------------------------------------- /core/client/app/scripts/controllers/app-controller.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Vardyger 3 | * Copyright(c) 2015 Rob Ferguson 4 | * MIT Licensed 5 | */ 6 | 7 | 'use strict'; 8 | 9 | /* 10 | * Dependency Injection Syntax and AngularJS 11 | * The notation that we have used is one of the two ways in which we can declare AngularJS controllers 12 | * (or services, directives, or filters). The style we have used, which is also the recommended way, 13 | * is the safe-style of Dependency Injection, or declaration. 14 | */ 15 | 16 | angular.module('vardyger') 17 | .controller('AppController', ['$log', '$scope', '$ionicModal', '$translate', 'AuthenticationService', 18 | function( 19 | $log, // inject the $log service 20 | $scope, // inject the $scope service 21 | $ionicModal, // inject the $ionicModal service 22 | $translate, // inject the $translate service 23 | AuthenticationService // inject the AuthenticationService service 24 | ) { 25 | 26 | $log.info('AppController'); 27 | 28 | // AuthenticationService.logout(); 29 | 30 | $scope.switchLanguage = function(key) { 31 | $log.info('switchLanguage() to ' + key); 32 | $translate.use(key); 33 | }; 34 | 35 | // Login / Logout 36 | 37 | $ionicModal.fromTemplateUrl('templates/login-template.html', { 38 | scope: $scope, 39 | animation: 'slide-in-up', // fade-in, reverse, slide-in-up 40 | focusFirstInput: true 41 | }).then(function(modal) { 42 | $scope.loginModal = modal; 43 | }); 44 | 45 | $scope.isLoggedIn = function() { 46 | // $log.info('AppController - isLoggedIn()'); 47 | return AuthenticationService.isLoggedIn(); 48 | }; 49 | 50 | $scope.logout = function() { 51 | // $log.info('AppController - logout()'); 52 | AuthenticationService.logout(); 53 | }; 54 | 55 | $scope.$on('$destroy', function() { 56 | $log.info('AppController - $destroy'); 57 | $scope.loginModal.remove(); 58 | }); 59 | 60 | }]); 61 | 62 | -------------------------------------------------------------------------------- /core/client/app/scripts/controllers/editor-controller.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Vardyger 3 | * Copyright(c) 2015 Rob Ferguson 4 | * MIT Licensed 5 | */ 6 | 7 | 'use strict'; 8 | 9 | // Reference the 'vardyger' module to attach a controller 10 | 11 | angular.module('vardyger') 12 | .controller('EditorController', 13 | function( 14 | $log, // inject the $log service 15 | $scope, // inject the $scope service 16 | post // inject Post model 17 | ) { 18 | 19 | $log.info('EditorController'); 20 | 21 | $scope.item = post; 22 | $scope.preview = false; 23 | 24 | $scope.previewPost = function(flag) { 25 | $scope.preview = flag; 26 | }; 27 | 28 | $scope.isPreview = function() { 29 | return $scope.preview; 30 | }; 31 | 32 | }); 33 | 34 | -------------------------------------------------------------------------------- /core/client/app/scripts/controllers/login-controller.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Vardyger 3 | * Copyright(c) 2015 Rob Ferguson 4 | * MIT Licensed 5 | */ 6 | 7 | 'use strict'; 8 | 9 | // Reference the 'vardyger' module to attach a controller 10 | 11 | angular.module('vardyger') 12 | .controller('LoginController', 13 | function( 14 | $log, // inject the $log service 15 | $scope, // inject the $scope service 16 | $http, // inject the $http service 17 | $state, // inject the $state service 18 | AuthenticationService // inject the AuthenticationService service 19 | ) { 20 | 21 | $log.info('LoginController'); 22 | 23 | $scope.message = ''; 24 | 25 | $scope.credentials = { 26 | grant_type: 'password', 27 | username: null, 28 | password: null, 29 | client_id: 'ghost-admin' 30 | }; 31 | 32 | $scope.login = function() { 33 | AuthenticationService.login($scope.credentials); 34 | }; 35 | 36 | $scope.$on('event:auth-loginRequired', function(e, rejection) { 37 | $log.info('LoginController - event:auth-loginRequired'); 38 | $scope.loginModal.show(); 39 | }); 40 | 41 | $scope.$on('event:auth-loginConfirmed', function() { 42 | $log.info('LoginController - event:auth-loginConfirmed'); 43 | $scope.loginModal.hide(); 44 | }); 45 | 46 | $scope.$on('event:auth-login-failed', function(e, status) { 47 | $log.info('LoginController - event:auth-login-failed'); 48 | var error = 'Login failed.'; 49 | if (status === 401) { 50 | error = 'Invalid Username or Password.'; 51 | } 52 | $scope.message = error; 53 | }); 54 | 55 | $scope.$on('event:auth-logout-complete', function() { 56 | $log.info('LoginController - event:auth-logout-complete'); 57 | $state.go('app.welcome'); 58 | }); 59 | 60 | }); 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /core/client/app/scripts/controllers/main-controller.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Vardyger 3 | * Copyright(c) 2015 Rob Ferguson 4 | * MIT Licensed 5 | */ 6 | 7 | 'use strict'; 8 | 9 | // Reference the 'vardyger' module to attach a controller 10 | 11 | angular.module('vardyger') 12 | .controller('MainController', 13 | function( 14 | $log, // inject the $log service 15 | $scope, // inject the $scope service 16 | $http, // inject the $http service 17 | posts, // inject the resolved posts data 18 | $timeout, 19 | $ionicScrollDelegate 20 | ) { 21 | 22 | $log.info('MainController'); 23 | 24 | $scope.listItems = {}; 25 | 26 | // Or you can use $state.reload() 27 | 28 | $scope.$on('$ionicView.beforeEnter', function() { 29 | // The view has fully entered and is now the active view. 30 | // This event will fire, whether it was the first load or a cached view. 31 | $log.info('MainController - $ionicView.beforeEnter'); 32 | 33 | // $ionicHistory.clearHistory(); 34 | }); 35 | 36 | // Values on $scope are called models and are also available in views. 37 | 38 | // $scope.listItems = posts; 39 | 40 | $http.get('https://posts') 41 | .success(function (data, status, headers, config) { 42 | $log.info('MainController - $http.get()'); 43 | 44 | // $scope.listItems = data; 45 | 46 | // See: http://forum.ionicframework.com/t/ngfx-animation-in-ionic/15176 47 | 48 | for (var i = 0; i < data.length; i++) { 49 | (function() { 50 | var j = i; 51 | $timeout(function(){ 52 | $scope.listItems[j] = data[j]; 53 | $ionicScrollDelegate.resize(); 54 | }, j * 300); 55 | })(); 56 | } 57 | }) 58 | .error(function (data, status, headers, config) { 59 | $log.error('An error occurred: ' + status); 60 | }); 61 | 62 | }); 63 | 64 | -------------------------------------------------------------------------------- /core/client/app/scripts/controllers/preview-controller.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Vardyger 3 | * Copyright(c) 2015 Rob Ferguson 4 | * MIT Licensed 5 | */ 6 | 7 | 'use strict'; 8 | 9 | // Reference the 'vardyger' module to attach a controller 10 | 11 | angular.module('vardyger') 12 | .controller('PreviewController', 13 | function( 14 | $log, // inject the $log service 15 | $scope, // inject the $scope service 16 | post // inject resolved post data 17 | ) { 18 | 19 | $log.info('PreviewController'); 20 | 21 | $scope.item = post; 22 | 23 | // $log.info('$scope.item: ', $scope.item); 24 | 25 | }); 26 | 27 | /* 28 | 29 | $scope.editPost = function() { 30 | 31 | $log.info('editPost()'); 32 | 33 | // $state.go('app.editor({postId: item.post.id})'); 34 | 35 | }; 36 | 37 | */ 38 | -------------------------------------------------------------------------------- /core/client/app/scripts/locales/de.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | "MAIN_TEMPLATE_TITLE": "Inhalt", 4 | "PREVIEW_TEMPLATE_TITLE": "Vorschau", 5 | "EDITOR_TEMPLATE_TITLE": "Editor", 6 | 7 | "WELCOME": "Willkommen in der Admin UI :)", 8 | 9 | "LOGIN_BUTTON": "EINLOGGEN", 10 | "FORGOTTEN_PASSWORD": "Passwort vergessen?", 11 | 12 | "CONTENT": "Inhalt", 13 | "NEW_POST": "neuer Beitrag", 14 | "SETTINGS": "Einstellungen", 15 | "LOGIN": "Einloggen", 16 | "LOGOUT": "abmelden", 17 | 18 | "ALL_POSTS": "Alle Beiträge", 19 | "NO_POSTS": "keine Einträge :(", 20 | "EDIT": "BEARBEITEN", 21 | "MARKDOWN": "MARKDOWN", 22 | "PREVIEW": "VORSCHAU", 23 | "UPDATE_POST": "UPDATE BEITRAG" 24 | 25 | } 26 | -------------------------------------------------------------------------------- /core/client/app/scripts/locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | 3 | "MAIN_TEMPLATE_TITLE": "Content", 4 | "PREVIEW_TEMPLATE_TITLE": "Preview", 5 | "EDITOR_TEMPLATE_TITLE": "Editor", 6 | 7 | "WELCOME": "Welcome to the Admin UI :)", 8 | 9 | "LOGIN_BUTTON": "LOG IN", 10 | "FORGOTTEN_PASSWORD": "Forgotten password?", 11 | 12 | "CONTENT": "Content", 13 | "NEW_POST": "New Post", 14 | "SETTINGS": "Settings", 15 | "LOGIN": "Login", 16 | "LOGOUT": "Logout", 17 | 18 | "ALL_POSTS": "ALL POSTS", 19 | "NO_POSTS": "No posts :(", 20 | "EDIT": "EDIT", 21 | "MARKDOWN": "MARKDOWN", 22 | "PREVIEW": "PREVIEW", 23 | "UPDATE_POST": "UPDATE POST" 24 | 25 | } 26 | -------------------------------------------------------------------------------- /core/client/app/scripts/services/authentication-service.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Vardyger 3 | * Copyright(c) 2015 Rob Ferguson 4 | * MIT Licensed 5 | */ 6 | 7 | 'use strict'; 8 | 9 | // Reference the 'vardyger' module to attach a factory 10 | 11 | angular.module('vardyger') 12 | .factory('AuthenticationService', 13 | function( 14 | $log, // inject the $log service 15 | $rootScope, // inject the $rootScope service 16 | $http, // inject the $http service 17 | authService, // inject the authService service 18 | localStorageService // inject the localStorageService service 19 | ) { 20 | 21 | $log.info('AuthenticationService'); 22 | 23 | var loggedIn = false; 24 | 25 | var service = { 26 | 27 | login: function(credentials) { 28 | 29 | $log.info('AuthenticationService.login()'); 30 | 31 | $http.post('https://login', { user: credentials }, { ignoreAuthModule: true }) 32 | 33 | .success(function (data, status, headers, config) { 34 | 35 | $log.info('AuthenticationService.login() - success'); 36 | 37 | loggedIn = true; 38 | 39 | $http.defaults.headers.common.Authorization = data.authorizationToken; 40 | // A more secure approach would be to store the token in SharedPreferences 41 | // for Android and keychain for iOS 42 | localStorageService.set('authorizationToken', data.authorizationToken); 43 | 44 | // Need to inform the http-auth-interceptor that the user has logged in successfully. 45 | // To do this, we pass in a function that will configure the request headers with the 46 | // authorization token so previously failed requests(aka with status == 401) will be 47 | // resent with the authorization token placed in the header 48 | authService.loginConfirmed(data, function(config) { 49 | config.headers.Authorization = data.authorizationToken; 50 | return config; 51 | }); 52 | }) 53 | 54 | .error(function (data, status, headers, config) { 55 | $log.info('AuthenticationService.login() - error'); 56 | $rootScope.$broadcast('event:auth-login-failed', status); 57 | }); 58 | }, 59 | 60 | isLoggedIn: function() { 61 | $log.info('AuthenticationService.isLoggedIn()'); 62 | return loggedIn; 63 | }, 64 | 65 | loginCancelled: function() { 66 | $log.info('loginCancelled()'); 67 | authService.loginCancelled(); 68 | }, 69 | 70 | logout: function() { 71 | 72 | $log.info('AuthenticationService.logout()'); 73 | 74 | loggedIn = false; 75 | 76 | $http.post('https://logout', {}, { ignoreAuthModule: true }) 77 | .finally(function(data) { 78 | localStorageService.remove('authorizationToken'); 79 | delete $http.defaults.headers.common.Authorization; 80 | $rootScope.$broadcast('event:auth-logout-complete'); 81 | }); 82 | } 83 | 84 | }; 85 | 86 | return service; 87 | 88 | }); 89 | -------------------------------------------------------------------------------- /core/client/app/scripts/services/posts-service.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Vardyger 3 | * Copyright(c) 2015 Rob Ferguson 4 | * MIT Licensed 5 | */ 6 | 7 | 'use strict'; 8 | 9 | // Reference the 'vardyger' module to attach a service 10 | 11 | angular.module('vardyger') 12 | .service('PostsService', 13 | function( 14 | $log, // inject the $log service 15 | $q // inject the $q service 16 | ) { 17 | 18 | $log.info('PostsService'); 19 | 20 | var model = [ 21 | 22 | { 23 | metaTitle: 'Ionic Style Guide', 24 | metaDescription: 'AngularJS is the toolset that underpins the Ionic Framework.', 25 | post: { 26 | id: '1', 27 | title: 'Ionic Style Guide', 28 | html: '

AngularJS is the toolset that underpins the Ionic Framework.

' + 29 | '

This means that if you want to use the Ionic Framework to develop hybrid mobile applications' + 30 | ' then you will need to understand how Angular web applications are built and structured. A great ' + 31 | 'place to start is to take a look at the Angular project structure templates created by popular ' + 32 | 'Yeoman generators and projects like ' + 33 | 'ng-boilerplate

' + 34 | '

Yeoman

' + 35 | '

Yeoman provides a generator ecosystem ' + 36 | 'that helps you to kickstart new projects. A generator is basically a plugin that can be run with the ' + 37 | 'yo command to create the scaffolding for a new project:

', 38 | markdown: 'AngularJS is the toolset that underpins the Ionic Framework.' + 39 | 'This means that if you want to use the Ionic Framework to develop hybrid mobile applications then you ' + 40 | 'will need to understand how Angular web applications are built and structured. A great place to start ' + 41 | 'is to take a look at the Angular project structure templates created by popular Yeoman ' + 42 | 'generators and projects like ' + 43 | 'ng-boilerplate ' + 44 | '### Yeoman' + 45 | 'Yeoman provides a generator ecosystem ' + 46 | 'that helps you to kickstart new projects. A generator is basically a plugin that can be run with ' + 47 | 'the `yo` command to create the scaffolding for a new project:' 48 | } 49 | }, 50 | 51 | { 52 | metaTitle: 'Customising Ionic with Sass', 53 | metaDescription: 'In a previous post, ...', 54 | post: { 55 | id: '2', 56 | title: 'Customising Ionic with Sass', 57 | html: '

In a previous post, ...

', 58 | markdown: 'In a previous post, ...' 59 | } 60 | }, 61 | 62 | { 63 | metaTitle: 'Ionic, Angular and Cordova', 64 | metaDescription: 'In a previous post, ...', 65 | post: { 66 | id: '3', 67 | title: 'Ionic, Angular and Cordova', 68 | html: '

In a previous post, ...

', 69 | markdown: 'In a previous post, ...' 70 | } 71 | }, 72 | 73 | { 74 | metaTitle: 'Annotating JavaScript using JSDoc tags', 75 | metaDescription: 'In a previous post, ...', 76 | post: { 77 | id: '4', 78 | title: 'Annotating JavaScript using JSDoc tags', 79 | html: '

In a previous post, ...

', 80 | markdown: 'In a previous post, ...' 81 | } 82 | }, 83 | 84 | { 85 | metaTitle: 'Express, Handlebars and Ghost Themes', 86 | metaDescription: 'In a previous post, ...', 87 | post: { 88 | id: '5', 89 | title: 'Express, Handlebars and Ghost Themes', 90 | html: '

In a previous post, ...

', 91 | markdown: 'In a previous post, ...' 92 | } 93 | }, 94 | 95 | { 96 | metaTitle: 'Swagger, Express, and Content Negotiation', 97 | metaDescription: 'In a previous post, ...', 98 | post: { 99 | id: '6', 100 | title: 'Swagger, Express, and Content Negotiation', 101 | html: '

In a previous post, ...

', 102 | markdown: 'In a previous post, ...' 103 | } 104 | }, 105 | 106 | { 107 | metaTitle: 'The Vardyger publishing platform :)', 108 | metaDescription: 'In a previous post, ...', 109 | post: { 110 | id: '7', 111 | title: 'The Vardyger publishing platform :)', 112 | html: '

In a previous post, ...

', 113 | markdown: 'In a previous post, ...' 114 | } 115 | } 116 | 117 | ]; 118 | 119 | this.getModel = function() { 120 | 121 | $log.info('PostsService.getModel()'); 122 | 123 | return model; 124 | }; 125 | 126 | this.findPosts = function() { 127 | 128 | // $log.info('PostsService.findPosts()'); 129 | 130 | return model; 131 | }; 132 | 133 | this.findPostById = function(id) { 134 | 135 | // $log.info('PostsService.findPostById(): ' + id); 136 | 137 | var deferred = $q.defer(); 138 | 139 | // Note: model.forEach NOT this.model.forEach 140 | 141 | model.forEach(function(item) { 142 | if (item.post.id === id) { 143 | // $log.info('item.post.id === id'); 144 | deferred.resolve(item); 145 | } 146 | }); 147 | 148 | return deferred.promise; 149 | }; 150 | 151 | }); 152 | 153 | 154 | /* 155 | 156 | // https://docs.angularjs.org/api/ng/service/$sce 157 | 158 | // $log.info('model.length: ' + model.length); 159 | 160 | setTimeout(function() { 161 | model.forEach(function(item) { 162 | if (item.post.id === id) { 163 | $log.info('item.post.id === id'); 164 | deferred.resolve(item); 165 | } 166 | }); 167 | }, 2000); 168 | 169 | 170 | 171 | $scope.item = { 172 | 173 | metaTitle: 'metaTitle', 174 | metaDescription: 'metaDescription', 175 | post: { 176 | id: 'id', 177 | title: 'Annotating JavaScript using JSDoc tags', 178 | excerpt: '', 179 | html: '', 180 | url: '', 181 | image: '', 182 | featured: false, 183 | page: false, 184 | // state: 'draft', 185 | // locale: 'en_GB', 186 | publishedAt: '', 187 | updatedAt: '', 188 | createdAt: '', 189 | author: { 190 | name: 'Rob Ferguson', 191 | location: 'Sydney, Australia' 192 | }, 193 | tags: '' 194 | } 195 | 196 | }; 197 | 198 | */ 199 | 200 | -------------------------------------------------------------------------------- /core/client/app/styles/main.scss: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | 3 | /** 4 | * 5 | * PATH TO THIS FILE: app/styles/main.scss 6 | * 7 | * This includes all variables. We put them all (both ionic overrides and 8 | * our own variables) in one file so it is easy for anyone who @includes 9 | * our scss to locate and edit our variables. 10 | * 11 | **/ 12 | 13 | @import "variables"; 14 | 15 | /** 16 | * 17 | * This includes the SASS/SCSS version of the ionic framework so that we can 18 | * customize it by overriding it's variables. To use this we need to make sure 19 | * that the CSS version is not included in app/index.html 20 | * 21 | **/ 22 | 23 | @import "../bower_components/ionic/scss/ionic"; 24 | 25 | // @import "../bower_components/ionic/scss/ionicons/ionicons"; 26 | 27 | /** 28 | * 29 | * These are the actual components of our apps that consume variables. We can 30 | * override ionic's own styles here or add additional styles of our own. 31 | * 32 | **/ 33 | 34 | @import "styles"; 35 | 36 | 37 | -------------------------------------------------------------------------------- /core/client/app/styles/styles.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * PATH TO THIS FILE: app/styles/styles.scss 4 | * 5 | * Notice that here we define styles but do not define variables. 6 | * Variables should all be defined ahead of time. If we define any 7 | * variables here, then they will be local to this file, and will 8 | * not reset the globals. 9 | * 10 | **/ 11 | 12 | // TODO: 13 | // Update Gruntfile.js so that it only compiles main.scss and not 14 | // all .scss files in the styles directory. 15 | @import "variables"; 16 | // e.g., grunt serve --force v grunt serve 17 | 18 | /** 19 | * Typography, see bower_components/ionic/scss/_types.scss 20 | */ 21 | 22 | // Body text 23 | // ------------------------- 24 | 25 | p { 26 | margin: 0 0 ($line-height-computed / 2); 27 | font-weight: $body-font-weight; 28 | } 29 | 30 | // Emphasis & misc 31 | // ------------------------- 32 | 33 | small { 34 | font-size: 60%; // 85% 35 | font-weight: $small-font-weight; 36 | } 37 | 38 | // Headings 39 | // ------------------------- 40 | 41 | h1, .h1 { font-size: floor($font-size-base * 2.80); } // ~36px 2.60 42 | h2, .h2 { font-size: floor($font-size-base * 2.15); } // ~30px 43 | h3, .h3 { font-size: ceil($font-size-base * 2.00); } // ~24px 1.7 44 | h4, .h4 { font-size: ceil($font-size-base * 1.25); } // ~18px 45 | h5, .h5 { font-size: $font-size-base; } 46 | h6, .h6 { font-size: ceil($font-size-base * 0.85); } // ~12px 47 | 48 | .v-item { 49 | padding-top: 6px; 50 | padding-bottom: 6px; 51 | } 52 | 53 | .v-content { 54 | background-color: white; 55 | } 56 | 57 | .item.wrap, .wrap.v-item, .item-content.wrap { 58 | white-space: normal; 59 | } 60 | 61 | .v-icon-item-left { 62 | font-size: 24px; 63 | vertical-align: text-top; 64 | } 65 | 66 | .post-title { 67 | padding-top: 6px; 68 | padding-left: 12px; 69 | padding-right: 12px; 70 | } 71 | 72 | .post-content { 73 | padding-top: 6px; 74 | padding-left: 14px; 75 | padding-right: 14px; 76 | } 77 | 78 | textarea { 79 | // height: auto; 80 | resize: none; 81 | } 82 | 83 | .markdown-editor { 84 | width: 100%; 85 | } 86 | 87 | // _bar.scss 88 | .bar-subsubheader { 89 | top: $bar-height + $bar-height; 90 | display: block; 91 | 92 | height: $bar-subheader-height; 93 | } 94 | 95 | // _scaffolding.scss 96 | .has-subsubheader { 97 | top: $bar-height + $bar-subheader-height + $bar-subheader-height; 98 | } 99 | 100 | // Misc 101 | // ------------------------- 102 | 103 | .vertical-center-container { 104 | height: 100%; 105 | 106 | @include display-flex(); 107 | @include justify-content(center); 108 | @include align-items(center); 109 | 110 | .vertical-center { 111 | width: 100%; 112 | 113 | @include display-flex(); 114 | @include flex-direction(column); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /core/client/app/styles/variables.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * PATH TO THIS FILE: app/styles/variables.scss 4 | * 5 | * In this file we're smoothly overriding any ionic variables that have 6 | * existing defaults inside the framework variables file. We're also defining 7 | * our own variables that we can use in our app's components. Essentially we're 8 | * setting the global variables for our app here. 9 | * 10 | * For a list of the possible variables that you can override, see bower_components/ionic/scss/_variables.scss 11 | * 12 | * Note: we add !default to all variables so that they can be overridden later on if need be. 13 | * 14 | **/ 15 | 16 | // The path to the ionicons font files, relative to the built CSS in www/styles 17 | // $ionicons-font-path: "../fonts" !default; 18 | 19 | // Colors 20 | // ------------------------------- 21 | 22 | $light: #fff !default; 23 | $stable: #f8f8f8 !default; 24 | $positive: #387ef5 !default; 25 | $calm: #11c1f3 !default; 26 | $balanced: #9FBB58 !default; 27 | $energized: #ffc900 !default; 28 | $assertive: #ef473a !default; 29 | $royal: #886aea !default; 30 | $dark: #242628 !default; 31 | 32 | // Base 33 | // ------------------------------- 34 | 35 | $font-family-sans-serif: "Open Sans", sans-serif !default; 36 | $font-family-light-sans-serif: "HelveticaNeue-Light", "Roboto-Light", "Segoe UI-Light", sans-serif-light !default; 37 | $font-family-serif: serif !default; 38 | $font-family-monospace: monospace !default; 39 | 40 | $font-family-base: $font-family-sans-serif !default; 41 | $font-size-base: 18px !default; // 14px 42 | $font-size-large: 18px !default; 43 | $font-size-small: 9px !default; // 11px 44 | 45 | $line-height-base: 1.428571429 !default; // 20/14 46 | $line-height-computed: floor($font-size-base * $line-height-base) !default; // ~20px 47 | $line-height-large: 1.33 !default; 48 | $line-height-small: 1.5 !default; 49 | 50 | $headings-font-family: $font-family-base !default; 51 | $headings-font-weight: bold !default; 52 | $headings-line-height: 1.2 !default; 53 | 54 | $base-background-color: #fff !default; 55 | $base-color: #000 !default; 56 | 57 | $link-color: $positive !default; 58 | $link-hover-color: darken($link-color, 15%) !default; 59 | 60 | $content-padding: 10px !default; 61 | 62 | $padding-base-vertical: 6px !default; 63 | $padding-base-horizontal: 12px !default; 64 | 65 | $padding-large-vertical: 10px !default; 66 | $padding-large-horizontal: 16px !default; 67 | 68 | $padding-small-vertical: 5px !default; 69 | $padding-small-horizontal: 10px !default; 70 | 71 | $border-radius-base: 4px !default; 72 | $border-radius-large: 6px !default; 73 | $border-radius-small: 3px !default; 74 | 75 | 76 | $body-font-weight: 200 !default; 77 | $small-font-weight: 400 !default; 78 | -------------------------------------------------------------------------------- /core/client/app/templates/editor-template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 |
7 |

8 | 10 |

11 |
12 | 13 |
14 |
{{item.post.title}}
15 |
16 | 17 |
18 | 19 | 20 |
21 |
22 | 24 | 26 |
27 |
28 | 29 | 30 | 31 |
32 | 34 |
35 | 36 |
37 |
38 |
39 | 40 |
41 | 42 | 43 | 48 | 49 | 50 |
51 | 52 | 57 | 58 | 66 | 67 | 70 | 71 | 74 | -------------------------------------------------------------------------------- /core/client/app/templates/login-template.html: -------------------------------------------------------------------------------- 1 | 29 | 30 | 35 | -------------------------------------------------------------------------------- /core/client/app/templates/main-template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 |
6 | 7 |
8 | 9 |
10 | 11 | 12 | 13 | 18 | 19 | 20 | 24 | {{listItem.post.title}} 25 | 26 | 27 | 28 | 29 | 30 |
31 |

32 | 33 | 37 | 38 | 39 |  Published a few days ago 40 |

41 |
42 | 43 |
44 |
45 | 46 |
47 | 48 |
49 | 50 | 55 | 56 | 58 | 66 | 67 | 69 | -------------------------------------------------------------------------------- /core/client/app/templates/preview-template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | 12 | 13 |
14 |

{{item.post.title}}

15 |
16 |
17 | 18 |
19 | 20 |
21 | 22 | 31 | -------------------------------------------------------------------------------- /core/client/app/templates/side-menu-template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | {{ 'CONTENT' | translate }} 35 | 36 | 37 | 38 | 39 | {{ 'NEW_POST' | translate }} 40 | 41 | 42 | 43 | 44 | {{ 'SETTINGS' | translate }} 45 | 46 | 47 | 48 | 49 | {{ 'LOGOUT' | translate }} 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 68 | -------------------------------------------------------------------------------- /core/client/app/templates/welcome-template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |

6 |

Tap the 7 | nav-icon to view the side menu. 8 |

9 |

Choose "{{ 'CONTENT' | translate }}" to view a list of posts. 10 |

11 |

The "{{ 'LOGOUT' | translate }}" menu item will be displayed when you are logged in. 12 |

13 | 14 |
15 | 16 |
17 | 18 | 27 | -------------------------------------------------------------------------------- /core/client/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Vardyger", 3 | "version": "1.0.0", 4 | "dependencies": { 5 | "ionic": "v1.0.0", 6 | "ionic-contrib-icon": "v0.0.3", 7 | "angular-translate": "~2.7.2", 8 | "angular-translate-loader-static-files": "~2.7.2", 9 | "angular-http-auth": "~1.2.2", 10 | "angular-local-storage": "~0.2.2", 11 | "ngFx": "~1.1.0" 12 | }, 13 | "devDependencies": { 14 | "angular-mocks": "~1.4.3" 15 | }, 16 | "resolutions": { 17 | "angular": "1.3.13" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /core/client/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Vardyger 4 | 5 | A sample Apache Cordova application that responds to the deviceready event. 6 | 7 | 8 | The Vardyger Foundation 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 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /core/client/hooks/README.md: -------------------------------------------------------------------------------- 1 | 21 | # Cordova Hooks 22 | 23 | Cordova Hooks represent special scripts which could be added by application and plugin developers or even by your own build system to customize cordova commands. Hook scripts could be defined by adding them to the special predefined folder (`/hooks`) or via configuration files (`config.xml` and `plugin.xml`) and run serially in the following order: 24 | * Application hooks from `/hooks`; 25 | * Application hooks from `config.xml`; 26 | * Plugin hooks from `plugins/.../plugin.xml`. 27 | 28 | __Remember__: Make your scripts executable. 29 | 30 | __Note__: `.cordova/hooks` directory is also supported for backward compatibility, but we don't recommend using it as it is deprecated. 31 | 32 | ## Supported hook types 33 | The following hook types are supported: 34 | 35 | after_build/ 36 | after_compile/ 37 | after_docs/ 38 | after_emulate/ 39 | after_platform_add/ 40 | after_platform_rm/ 41 | after_platform_ls/ 42 | after_plugin_add/ 43 | after_plugin_ls/ 44 | after_plugin_rm/ 45 | after_plugin_search/ 46 | after_plugin_install/ <-- Plugin hooks defined in plugin.xml are executed exclusively for a plugin being installed 47 | after_prepare/ 48 | after_run/ 49 | after_serve/ 50 | before_build/ 51 | before_compile/ 52 | before_docs/ 53 | before_emulate/ 54 | before_platform_add/ 55 | before_platform_rm/ 56 | before_platform_ls/ 57 | before_plugin_add/ 58 | before_plugin_ls/ 59 | before_plugin_rm/ 60 | before_plugin_search/ 61 | before_plugin_install/ <-- Plugin hooks defined in plugin.xml are executed exclusively for a plugin being installed 62 | before_plugin_uninstall/ <-- Plugin hooks defined in plugin.xml are executed exclusively for a plugin being uninstalled 63 | before_prepare/ 64 | before_run/ 65 | before_serve/ 66 | pre_package/ <-- Windows 8 and Windows Phone only. 67 | 68 | ## Ways to define hooks 69 | ### Via '/hooks' directory 70 | To execute custom action when corresponding hook type is fired, use hook type as a name for a subfolder inside 'hooks' directory and place you script file here, for example: 71 | 72 | # script file will be automatically executed after each build 73 | hooks/after_build/after_build_custom_action.js 74 | 75 | 76 | ### Config.xml 77 | 78 | Hooks can be defined in project's `config.xml` using `` elements, for example: 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | ... 89 | 90 | 91 | 92 | 93 | 94 | 95 | ... 96 | 97 | 98 | ### Plugin hooks (plugin.xml) 99 | 100 | As a plugin developer you can define hook scripts using `` elements in a `plugin.xml` like that: 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | ... 109 | 110 | 111 | `before_plugin_install`, `after_plugin_install`, `before_plugin_uninstall` plugin hooks will be fired exclusively for the plugin being installed/uninstalled. 112 | 113 | ## Script Interface 114 | 115 | ### Javascript 116 | 117 | If you are writing hooks in Javascript you should use the following module definition: 118 | ```javascript 119 | module.exports = function(context) { 120 | ... 121 | } 122 | ``` 123 | 124 | You can make your scipts async using Q: 125 | ```javascript 126 | module.exports = function(context) { 127 | var Q = context.requireCordovaModule('q'); 128 | var deferral = new Q.defer(); 129 | 130 | setTimeout(function(){ 131 | console.log('hook.js>> end'); 132 | deferral.resolve(); 133 | }, 1000); 134 | 135 | return deferral.promise; 136 | } 137 | ``` 138 | 139 | `context` object contains hook type, executed script full path, hook options, command-line arguments passed to Cordova and top-level "cordova" object: 140 | ```json 141 | { 142 | "hook": "before_plugin_install", 143 | "scriptLocation": "c:\\script\\full\\path\\appBeforePluginInstall.js", 144 | "cmdLine": "The\\exact\\command\\cordova\\run\\with arguments", 145 | "opts": { 146 | "projectRoot":"C:\\path\\to\\the\\project", 147 | "cordova": { 148 | "platforms": ["wp8"], 149 | "plugins": ["com.plugin.withhooks"], 150 | "version": "0.21.7-dev" 151 | }, 152 | "plugin": { 153 | "id": "com.plugin.withhooks", 154 | "pluginInfo": { 155 | ... 156 | }, 157 | "platform": "wp8", 158 | "dir": "C:\\path\\to\\the\\project\\plugins\\com.plugin.withhooks" 159 | } 160 | }, 161 | "cordova": {...} 162 | } 163 | 164 | ``` 165 | `context.opts.plugin` object will only be passed to plugin hooks scripts. 166 | 167 | You can also require additional Cordova modules in your script using `context.requireCordovaModule` in the following way: 168 | ```javascript 169 | var Q = context.requireCordovaModule('q'); 170 | ``` 171 | 172 | __Note__: new module loader script interface is used for the `.js` files defined via `config.xml` or `plugin.xml` only. 173 | For compatibility reasons hook files specified via `/hooks` folders are run via Node child_process spawn, see 'Non-javascript' section below. 174 | 175 | ### Non-javascript 176 | 177 | Non-javascript scripts are run via Node child_process spawn from the project's root directory and have the root directory passes as the first argument. All other options are passed to the script using environment variables: 178 | 179 | * CORDOVA_VERSION - The version of the Cordova-CLI. 180 | * CORDOVA_PLATFORMS - Comma separated list of platforms that the command applies to (e.g.: android, ios). 181 | * CORDOVA_PLUGINS - Comma separated list of plugin IDs that the command applies to (e.g.: org.apache.cordova.file, org.apache.cordova.file-transfer) 182 | * CORDOVA_HOOK - Path to the hook that is being executed. 183 | * CORDOVA_CMDLINE - The exact command-line arguments passed to cordova (e.g.: cordova run ios --emulate) 184 | 185 | If a script returns a non-zero exit code, then the parent cordova command will be aborted. 186 | 187 | ## Writing hooks 188 | 189 | We highly recommend writing your hooks using Node.js so that they are 190 | cross-platform. Some good examples are shown here: 191 | 192 | [http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/](http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/) 193 | 194 | Also, note that even if you are working on Windows, and in case your hook scripts aren't bat files (which is recommended, if you want your scripts to work in non-Windows operating systems) Cordova CLI will expect a shebang line as the first line for it to know the interpreter it needs to use to launch the script. The shebang line should match the following example: 195 | 196 | #!/usr/bin/env [name_of_interpreter_executable] 197 | -------------------------------------------------------------------------------- /core/client/hooks/after_platform_add/install_plugins.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Install all plugins listed in package.json 5 | */ 6 | var exec = require('child_process').exec; 7 | var path = require('path'); 8 | var sys = require('sys'); 9 | 10 | var packageJSON = require('../../package.json'); 11 | var cmd = process.platform === 'win32' ? 'cordova.cmd' : 'cordova'; 12 | var script = path.resolve(__dirname, '../../node_modules/cordova/bin', cmd); 13 | 14 | packageJSON.cordovaPlugins = packageJSON.cordovaPlugins || []; 15 | packageJSON.cordovaPlugins.forEach(function (plugin) { 16 | exec(script + ' plugin add ' + plugin, function (error, stdout, stderr) { 17 | sys.puts(stdout); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /core/client/hooks/after_plugin_add/register_plugins.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Push plugins to cordovaPlugins array after_plugin_add 5 | */ 6 | var fs = require('fs'); 7 | var packageJSON = require('../../package.json'); 8 | 9 | packageJSON.cordovaPlugins = packageJSON.cordovaPlugins || []; 10 | 11 | var fromEnv = process.env.CORDOVA_PLUGINS.split(','); 12 | for (var i = 0; i < fromEnv.length; i++) { 13 | var plugin = fromEnv[i]; 14 | 15 | if (packageJSON.cordovaPlugins.indexOf(plugin) !== -1) { 16 | packageJSON.cordovaPlugins.push(plugin); 17 | } 18 | } 19 | 20 | fs.writeFileSync('package.json', JSON.stringify(packageJSON, null, 2)); 21 | -------------------------------------------------------------------------------- /core/client/hooks/after_plugin_rm/deregister_plugins.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Remove plugins from cordovaPlugins array after_plugin_rm 5 | */ 6 | var fs = require('fs'); 7 | var _ = require('lodash'); 8 | var packageJSON = require('../../package.json'); 9 | 10 | packageJSON.cordovaPlugins = packageJSON.cordovaPlugins || []; 11 | _.each(process.env.CORDOVA_PLUGINS.split(','), function (plugin) { 12 | _.remove(packageJSON.cordovaPlugins, function (p) { return p === plugin; }); 13 | }); 14 | 15 | fs.writeFile('package.json', JSON.stringify(packageJSON, null, 2)); 16 | -------------------------------------------------------------------------------- /core/client/hooks/after_prepare/icons_and_splashscreens.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /** 3 | * Algorithm 4 | * [1] Look at all installed platforms 5 | * [2] Copy (non-destructive) icons and splash screens from platform to local RESOURCE_DIR 6 | * [3] Copy (destructive) matching icons and splash screens from RESOURCE_DIR to platform 7 | * 8 | * This ensures that local RESOURCE_DIR will be pre-scaffolded with icons and splash 9 | * screens generated by Cordova as placeholder ONLY for installed platforms and that 10 | * any modifications to local assets are reflected in the CORRECT Cordova platform 11 | * locations, without having to hardcode file paths. 12 | */ 13 | var fs = require('fs'); 14 | var path = require('path'); 15 | var _ = require('lodash'); 16 | var ncp = require('ncp'); 17 | var mkdirp = require('mkdirp'); 18 | var glob = require('glob'); 19 | var Orchestrator = require('orchestrator'); 20 | 21 | var BASES = { 22 | android: 'res', 23 | ios: 'Vardyger/Resources' 24 | }; 25 | var RESOURCE_DIR = 'resources'; 26 | 27 | // Helper function for file copying that ensures directory existence. 28 | function copyFile (src, dest, ncpOpts, callback) { 29 | var orchestrator = new Orchestrator(); 30 | var parts = dest.split(path.sep); 31 | var fileName = parts.pop(); 32 | var destDir = parts.join(path.sep); 33 | var destFile = path.resolve(destDir, fileName); 34 | orchestrator.add('ensureDir', function (done) { 35 | mkdirp(destDir, function (err) { 36 | done(err); 37 | }); 38 | }); 39 | orchestrator.add('copyFile', ['ensureDir'], function (done) { 40 | ncp(src, destFile, ncpOpts, function (err) { 41 | done(err); 42 | }); 43 | }); 44 | orchestrator.start('copyFile', function (err) { 45 | callback(err); 46 | }); 47 | } 48 | 49 | // Main 50 | var platforms = _.filter(fs.readdirSync('platforms'), function (file) { 51 | return fs.statSync(path.resolve('platforms', file)).isDirectory(); 52 | }); 53 | _.each(platforms, function (platform) { 54 | var base = path.resolve('platforms', platform, BASES[platform]); 55 | glob(base + '/**/*.png', function (err, files) { 56 | _.each(files, function (cordovaFile) { 57 | var orchestrator = new Orchestrator(); 58 | var parts = cordovaFile.split('/'); 59 | var fileName = parts.pop(); 60 | var localDir = path.resolve(RESOURCE_DIR, platform, _.last(parts)); 61 | var localFile = path.resolve(localDir, fileName); 62 | 63 | orchestrator.add('copyFromCordova', function (done) { 64 | copyFile(cordovaFile, localFile, { clobber: false }, function (err) { 65 | done(err); 66 | }); 67 | }); 68 | orchestrator.add('copyToCordova', ['copyFromCordova'], function (done) { 69 | copyFile(localFile, cordovaFile, { clobber: true }, function (err) { 70 | done(err); 71 | }); 72 | }); 73 | orchestrator.start('copyToCordova', function (err) { 74 | if (err) { console.error(err); } 75 | }); 76 | }); 77 | }); 78 | }); 79 | -------------------------------------------------------------------------------- /core/client/hooks/before_platform_add/init_directories.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * On a fresh clone, the local platforms/ and plugins/ directories will be 5 | * missing, so ensure they get created before the first platform is added. 6 | */ 7 | var mkdirp = require('mkdirp'); 8 | var path = require('path'); 9 | 10 | var platformsDir = path.resolve(__dirname, '../../platforms'); 11 | var pluginsDir = path.resolve(__dirname, '../../plugins'); 12 | 13 | mkdirp(platformsDir, function (err) { 14 | if (err) { console.error(err); } 15 | }); 16 | 17 | mkdirp(pluginsDir, function (err) { 18 | if (err) { console.error(err); } 19 | }); 20 | -------------------------------------------------------------------------------- /core/client/ionic.project: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "app_id": "" 4 | } -------------------------------------------------------------------------------- /core/client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Vardyger", 3 | "version": "0.0.0", 4 | "private": true, 5 | "dependencies": {}, 6 | "devDependencies": { 7 | "grunt": "~0.4.5", 8 | "glob": "~4.3.5", 9 | "grunt-autoprefixer": "~2.2.0", 10 | "grunt-wiredep": "^2.0.0", 11 | "ionic": "^1.3.7", 12 | "grunt-concurrent": "1.0.0", 13 | "grunt-contrib-clean": "~0.6.0", 14 | "grunt-contrib-compass": "~1.0.1", 15 | "grunt-contrib-concat": "~0.5.0", 16 | "grunt-contrib-connect": "~0.9.0", 17 | "grunt-contrib-copy": "~0.7.0", 18 | "grunt-contrib-cssmin": "~0.11.0", 19 | "grunt-contrib-htmlmin": "~0.3.0", 20 | "grunt-contrib-jshint": "~0.11.0", 21 | "grunt-contrib-uglify": "~0.7.0", 22 | "grunt-contrib-watch": "~0.6.1", 23 | "grunt-newer": "~1.1.0", 24 | "grunt-usemin": "~3.0.0", 25 | "grunt-ng-annotate": "~0.9.2", 26 | "grunt-ng-constant": "^1.0.0", 27 | "grunt-karma": "~0.10.1", 28 | "karma": "~0.12.31", 29 | "karma-mocha": "~0.1.10", 30 | "karma-chai": "~0.1.0", 31 | "karma-chrome-launcher": "~0.1.7", 32 | "karma-phantomjs-launcher": "~0.1.4", 33 | "karma-coverage": "~0.2.7", 34 | "jshint-stylish": "~1.0.0", 35 | "load-grunt-tasks": "~3.1.0", 36 | "time-grunt": "~1.0.0", 37 | "cordova": "~4.2.0", 38 | "lodash": "~3.1.0", 39 | "mkdirp": "~0.5.0", 40 | "ncp": "~1.0.1", 41 | "orchestrator": "~0.3.7", 42 | "ripple-emulator": "~0.9.24", 43 | "elementtree": "0.1.6", 44 | "plist": "1.1.0", 45 | "win-spawn": "^2.0.0" 46 | }, 47 | "engines": { 48 | "node": ">=0.10.0" 49 | }, 50 | "scripts": { 51 | "test": "grunt test" 52 | }, 53 | "cordovaPlugins": [ 54 | "org.apache.cordova.device", 55 | "org.apache.cordova.console", 56 | "com.ionic.keyboard" 57 | ], 58 | "cordovaPlatforms": [ 59 | "ios" 60 | ] 61 | } 62 | -------------------------------------------------------------------------------- /core/client/resources/android/drawable-hdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/drawable-hdpi/icon.png -------------------------------------------------------------------------------- /core/client/resources/android/drawable-land-hdpi/screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/drawable-land-hdpi/screen.png -------------------------------------------------------------------------------- /core/client/resources/android/drawable-land-ldpi/screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/drawable-land-ldpi/screen.png -------------------------------------------------------------------------------- /core/client/resources/android/drawable-land-mdpi/screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/drawable-land-mdpi/screen.png -------------------------------------------------------------------------------- /core/client/resources/android/drawable-land-xhdpi/screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/drawable-land-xhdpi/screen.png -------------------------------------------------------------------------------- /core/client/resources/android/drawable-ldpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/drawable-ldpi/icon.png -------------------------------------------------------------------------------- /core/client/resources/android/drawable-mdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/drawable-mdpi/icon.png -------------------------------------------------------------------------------- /core/client/resources/android/drawable-port-hdpi/screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/drawable-port-hdpi/screen.png -------------------------------------------------------------------------------- /core/client/resources/android/drawable-port-ldpi/screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/drawable-port-ldpi/screen.png -------------------------------------------------------------------------------- /core/client/resources/android/drawable-port-mdpi/screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/drawable-port-mdpi/screen.png -------------------------------------------------------------------------------- /core/client/resources/android/drawable-port-xhdpi/screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/drawable-port-xhdpi/screen.png -------------------------------------------------------------------------------- /core/client/resources/android/drawable-xhdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/drawable-xhdpi/icon.png -------------------------------------------------------------------------------- /core/client/resources/android/drawable/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/drawable/icon.png -------------------------------------------------------------------------------- /core/client/resources/android/icon/drawable-hdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/icon/drawable-hdpi-icon.png -------------------------------------------------------------------------------- /core/client/resources/android/icon/drawable-ldpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/icon/drawable-ldpi-icon.png -------------------------------------------------------------------------------- /core/client/resources/android/icon/drawable-mdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/icon/drawable-mdpi-icon.png -------------------------------------------------------------------------------- /core/client/resources/android/icon/drawable-xhdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/icon/drawable-xhdpi-icon.png -------------------------------------------------------------------------------- /core/client/resources/android/icon/drawable-xxhdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/icon/drawable-xxhdpi-icon.png -------------------------------------------------------------------------------- /core/client/resources/android/icon/drawable-xxxhdpi-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/icon/drawable-xxxhdpi-icon.png -------------------------------------------------------------------------------- /core/client/resources/android/splash/drawable-land-hdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/splash/drawable-land-hdpi-screen.png -------------------------------------------------------------------------------- /core/client/resources/android/splash/drawable-land-ldpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/splash/drawable-land-ldpi-screen.png -------------------------------------------------------------------------------- /core/client/resources/android/splash/drawable-land-mdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/splash/drawable-land-mdpi-screen.png -------------------------------------------------------------------------------- /core/client/resources/android/splash/drawable-land-xhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/splash/drawable-land-xhdpi-screen.png -------------------------------------------------------------------------------- /core/client/resources/android/splash/drawable-land-xxhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/splash/drawable-land-xxhdpi-screen.png -------------------------------------------------------------------------------- /core/client/resources/android/splash/drawable-land-xxxhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/splash/drawable-land-xxxhdpi-screen.png -------------------------------------------------------------------------------- /core/client/resources/android/splash/drawable-port-hdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/splash/drawable-port-hdpi-screen.png -------------------------------------------------------------------------------- /core/client/resources/android/splash/drawable-port-ldpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/splash/drawable-port-ldpi-screen.png -------------------------------------------------------------------------------- /core/client/resources/android/splash/drawable-port-mdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/splash/drawable-port-mdpi-screen.png -------------------------------------------------------------------------------- /core/client/resources/android/splash/drawable-port-xhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/splash/drawable-port-xhdpi-screen.png -------------------------------------------------------------------------------- /core/client/resources/android/splash/drawable-port-xxhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/splash/drawable-port-xxhdpi-screen.png -------------------------------------------------------------------------------- /core/client/resources/android/splash/drawable-port-xxxhdpi-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/android/splash/drawable-port-xxxhdpi-screen.png -------------------------------------------------------------------------------- /core/client/resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/icon.png -------------------------------------------------------------------------------- /core/client/resources/ios/icon/icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icon/icon-40.png -------------------------------------------------------------------------------- /core/client/resources/ios/icon/icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icon/icon-40@2x.png -------------------------------------------------------------------------------- /core/client/resources/ios/icon/icon-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icon/icon-50.png -------------------------------------------------------------------------------- /core/client/resources/ios/icon/icon-50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icon/icon-50@2x.png -------------------------------------------------------------------------------- /core/client/resources/ios/icon/icon-60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icon/icon-60.png -------------------------------------------------------------------------------- /core/client/resources/ios/icon/icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icon/icon-60@2x.png -------------------------------------------------------------------------------- /core/client/resources/ios/icon/icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icon/icon-60@3x.png -------------------------------------------------------------------------------- /core/client/resources/ios/icon/icon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icon/icon-72.png -------------------------------------------------------------------------------- /core/client/resources/ios/icon/icon-72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icon/icon-72@2x.png -------------------------------------------------------------------------------- /core/client/resources/ios/icon/icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icon/icon-76.png -------------------------------------------------------------------------------- /core/client/resources/ios/icon/icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icon/icon-76@2x.png -------------------------------------------------------------------------------- /core/client/resources/ios/icon/icon-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icon/icon-small.png -------------------------------------------------------------------------------- /core/client/resources/ios/icon/icon-small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icon/icon-small@2x.png -------------------------------------------------------------------------------- /core/client/resources/ios/icon/icon-small@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icon/icon-small@3x.png -------------------------------------------------------------------------------- /core/client/resources/ios/icon/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icon/icon.png -------------------------------------------------------------------------------- /core/client/resources/ios/icon/icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icon/icon@2x.png -------------------------------------------------------------------------------- /core/client/resources/ios/icons/icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icons/icon-40.png -------------------------------------------------------------------------------- /core/client/resources/ios/icons/icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icons/icon-40@2x.png -------------------------------------------------------------------------------- /core/client/resources/ios/icons/icon-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icons/icon-50.png -------------------------------------------------------------------------------- /core/client/resources/ios/icons/icon-50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icons/icon-50@2x.png -------------------------------------------------------------------------------- /core/client/resources/ios/icons/icon-60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icons/icon-60.png -------------------------------------------------------------------------------- /core/client/resources/ios/icons/icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icons/icon-60@2x.png -------------------------------------------------------------------------------- /core/client/resources/ios/icons/icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icons/icon-60@3x.png -------------------------------------------------------------------------------- /core/client/resources/ios/icons/icon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icons/icon-72.png -------------------------------------------------------------------------------- /core/client/resources/ios/icons/icon-72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icons/icon-72@2x.png -------------------------------------------------------------------------------- /core/client/resources/ios/icons/icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icons/icon-76.png -------------------------------------------------------------------------------- /core/client/resources/ios/icons/icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icons/icon-76@2x.png -------------------------------------------------------------------------------- /core/client/resources/ios/icons/icon-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icons/icon-small.png -------------------------------------------------------------------------------- /core/client/resources/ios/icons/icon-small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icons/icon-small@2x.png -------------------------------------------------------------------------------- /core/client/resources/ios/icons/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icons/icon.png -------------------------------------------------------------------------------- /core/client/resources/ios/icons/icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/icons/icon@2x.png -------------------------------------------------------------------------------- /core/client/resources/ios/splash/Default-568h@2x~iphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/splash/Default-568h@2x~iphone.png -------------------------------------------------------------------------------- /core/client/resources/ios/splash/Default-667h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/splash/Default-667h.png -------------------------------------------------------------------------------- /core/client/resources/ios/splash/Default-736h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/splash/Default-736h.png -------------------------------------------------------------------------------- /core/client/resources/ios/splash/Default-Landscape-736h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/splash/Default-Landscape-736h.png -------------------------------------------------------------------------------- /core/client/resources/ios/splash/Default-Landscape@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/splash/Default-Landscape@2x~ipad.png -------------------------------------------------------------------------------- /core/client/resources/ios/splash/Default-Landscape~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/splash/Default-Landscape~ipad.png -------------------------------------------------------------------------------- /core/client/resources/ios/splash/Default-Portrait@2x~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/splash/Default-Portrait@2x~ipad.png -------------------------------------------------------------------------------- /core/client/resources/ios/splash/Default-Portrait~ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/splash/Default-Portrait~ipad.png -------------------------------------------------------------------------------- /core/client/resources/ios/splash/Default@2x~iphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/splash/Default@2x~iphone.png -------------------------------------------------------------------------------- /core/client/resources/ios/splash/Default~iphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/ios/splash/Default~iphone.png -------------------------------------------------------------------------------- /core/client/resources/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/client/resources/splash.png -------------------------------------------------------------------------------- /core/client/test/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "browser": true, 4 | "esnext": true, 5 | "bitwise": true, 6 | "camelcase": true, 7 | "curly": true, 8 | "eqeqeq": true, 9 | "immed": true, 10 | "indent": 2, 11 | "latedef": true, 12 | "newcap": true, 13 | "noarg": true, 14 | "quotmark": "single", 15 | "regexp": true, 16 | "undef": true, 17 | "unused": true, 18 | "strict": true, 19 | "trailing": true, 20 | "smarttabs": true, 21 | "globals": { 22 | "after": false, 23 | "afterEach": false, 24 | "angular": false, 25 | "before": false, 26 | "beforeEach": false, 27 | "browser": false, 28 | "describe": false, 29 | "expect": false, 30 | "inject": false, 31 | "it": false, 32 | "jasmine": false, 33 | "spyOn": false 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /core/server/README.md: -------------------------------------------------------------------------------- 1 | # Skeleton project for Swagger 2 | -------------------------------------------------------------------------------- /core/server/api/controllers/README.md: -------------------------------------------------------------------------------- 1 | Place your controllers in this directory. 2 | -------------------------------------------------------------------------------- /core/server/api/controllers/posts.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Vardyger 3 | * Copyright(c) 2015 Rob Ferguson 4 | * MIT Licensed 5 | */ 6 | 7 | 'use strict'; 8 | 9 | /** 10 | * Module dependencies. 11 | * @private 12 | */ 13 | 14 | var util = require('util'); // console.log(util.inspect(anyObject)); 15 | var extend = util._extend; 16 | var mongoose = require('mongoose'); 17 | var status = require('../../utils/http-status-codes'); 18 | 19 | var Post = mongoose.model('Post'); 20 | 21 | var LOCATION = '/posts/'; 22 | var APPLICATION_JSON = 'application/json'; 23 | var TEXT_HTML = 'text/html'; 24 | 25 | /** 26 | * addPost 27 | * 28 | * creates a new post in the Posts collection.
29 | * Location (in the response header) is used to specify the URI of the newly created resource. 30 | * 31 | * @public 32 | * @param {req} req - The HTTP request object. 33 | * @param {res} res - The HTTP response object. 34 | * @return {id} string - The unique id of the resource that was created. 35 | * @see {@link http://expressjs.com/api.html#req} 36 | * @see {@link http://expressjs.com/api.html#res} 37 | */ 38 | function addPost(req, res) { 39 | 40 | var model = new Post(req.body); 41 | 42 | res.type(APPLICATION_JSON); 43 | 44 | model.save(function(error) { 45 | if (! error) { 46 | 47 | returnId(res, status.CREATED, model._id); 48 | 49 | /* 50 | 51 | res.format({ 52 | html: function(){ 53 | return res.status(201).send('

addPost()

'); 54 | }, 55 | json: function(){ 56 | // res.type(APPLICATION_JSON); 57 | returnId(res, status.CREATED, model._id); 58 | }, 59 | 'default': function() { 60 | returnError(res, status.NOT_ACCEPTABLE); 61 | } 62 | }) 63 | 64 | */ 65 | 66 | } else { 67 | returnError(res, status.INTERNAL_SERVER_ERROR); 68 | } 69 | }); 70 | } 71 | 72 | /** 73 | * findPosts 74 | * 75 | * returns all the posts in the Posts collection.
76 | * 77 | * When we return the array of posts, we don’t simply return the model as returned from the database. 78 | * That would expose internal implementation details. Instead, we pick the information we need and construct a 79 | * new object to return.

80 | * 81 | * Rule: GET must be used to retrieve a representation of a resource 82 | * 83 | * @public 84 | * @param {req} req - The HTTP request object. 85 | * @param {res} res - The HTTP response object. 86 | * @return {posts} posts - The Posts collection. 87 | * @see {@link http://expressjs.com/api.html#req} 88 | * @see {@link http://expressjs.com/api.html#res} 89 | */ 90 | function findPosts(req, res) { 91 | 92 | var filteredQuery = {}; 93 | 94 | res.type(APPLICATION_JSON); 95 | 96 | Post.find(filteredQuery, function(error, posts) { 97 | if (! error) { 98 | 99 | if (null === posts || undefined === posts) 100 | { 101 | returnError(res, status.NOT_FOUND); 102 | } 103 | 104 | // Node defaults to "transfer-encoding": "chunked" 105 | // Sending a 'Content-length' header will disable the default encoding. 106 | // res.setHeader("Content-Length", Buffer.byteLength(posts)); 107 | 108 | res.format({ 109 | html: function(){ 110 | res.type(TEXT_HTML); 111 | res.status(status.OK).send('

findPosts()

'); 112 | }, 113 | 114 | json: function(){ 115 | res.type(APPLICATION_JSON); 116 | res.status(status.OK).json(posts.map(function(a){ 117 | return { 118 | id: a._id, 119 | title: a.title, 120 | slug: a.slug, 121 | markdown: a.markdown, 122 | html: a.html, 123 | image: a.image, 124 | featured: a.featured, 125 | page: a.page, 126 | state: a.state, 127 | locale: a.locale, 128 | metaTitle: a.metaTitle, 129 | metaDescription: a.metaDescription 130 | } 131 | })); 132 | }, 133 | 134 | 'default': function() { 135 | returnError(res, status.NOT_ACCEPTABLE); 136 | } 137 | }) 138 | } else { 139 | returnError(res, status.INTERNAL_SERVER_ERROR); 140 | } 141 | }); 142 | } 143 | 144 | /** 145 | * findPostById 146 | * 147 | * returns a post in the Posts collection.
148 | * 149 | * When we return the post, we don’t simply return the model as returned from the database. 150 | * That would expose internal implementation details. Instead, we pick the information we need and construct a 151 | * new object to return.

152 | * 153 | * Rule: GET must be used to retrieve a representation of a resource 154 | * 155 | * @public 156 | * @param {req} req - The HTTP request object. 157 | * @param {res} res - The HTTP response object. 158 | * @return {post} post - A post from the Posts collection. 159 | * @see {@link http://expressjs.com/api.html#req} 160 | * @see {@link http://expressjs.com/api.html#res} 161 | */ 162 | function findPostById(req, res) { 163 | 164 | // Note: req.swagger.params.id.value not req.params.id 165 | // See: https://github.com/apigee-127/swagger-tools/blob/master/docs/Middleware.md 166 | var id = req.swagger.params.id.value, 167 | view = 'post', 168 | response; 169 | 170 | // console.log('id: ' + id); 171 | 172 | Post.findById(id).exec(function(error, model) { 173 | 174 | if (! error) { 175 | 176 | if (null === model || undefined === model) { returnError(res, status.NOT_FOUND); } 177 | 178 | response = formatResponse(model); 179 | // setResponseContext(req, res, response); 180 | 181 | res.format({ 182 | html: function() { 183 | // The view engine will return a content type of text/html and a status code of 200 by default. 184 | // res.type(TEXT_HTML); 185 | res.render(view, response); 186 | }, 187 | json: function() { 188 | res.type(APPLICATION_JSON); 189 | res.status(status.OK).send(JSON.stringify(response)); 190 | }, 191 | 'default': function() { returnError(res, status.NOT_ACCEPTABLE); } 192 | }) 193 | 194 | } else { 195 | returnError(res, status.INTERNAL_SERVER_ERROR); 196 | } 197 | }); 198 | } 199 | 200 | var url = 'http://robferguson.org'; 201 | // var url = 'http://localhost:10010'; 202 | 203 | /** 204 | * formatResponse 205 | * 206 | * returns a formatted response object see: {@link http://themes.ghost.org/v0.6.4/docs/post-context}
207 | * 208 | * Except where the doco is incorrect:
209 | * - 'content' helper returns (#post) this.html
210 | * - 'meta_title' helper returns this.metaTitle
211 | * - 'meta_description' helper returns this.metaDescription

212 | * 213 | * Rule: GET must be used to retrieve a representation of a resource 214 | * 215 | * @public 216 | * @param {model} model - The Post model. 217 | * @return {post} post - A Ghost formatted post object. 218 | */ 219 | function formatResponse(model) { 220 | return { 221 | meta_title: model.metaTitle, 222 | meta_description: model.metaDescription, 223 | navigation: [{ 224 | label: 'Home', 225 | url: url, 226 | current: false, 227 | slug: '' 228 | }, { 229 | label: 'About', 230 | url: url + '/about', 231 | current: false, 232 | slug: 'about' 233 | }], 234 | post: { 235 | id: model._id, 236 | title: model.title, 237 | excerpt: model.html, 238 | html: model.html, 239 | url: url, 240 | image: model.image, 241 | featured: model.featured, 242 | page: model.page, 243 | published_at: model.publishedAt, 244 | updated_at: model.updatedAt, 245 | created_at: model.createdAt, 246 | author: { 247 | name: 'Rob Ferguson', 248 | location: 'Sydney, Australia' 249 | }, 250 | tags: '' 251 | } 252 | } 253 | } 254 | 255 | // website: 256 | // bio: 257 | // excerpt: model.html.slice(0, 255), 258 | 259 | function setResponseContext(req, res, data) { 260 | 261 | var contexts = []; 262 | 263 | contexts.push('post'); 264 | 265 | res.locals.context = contexts; 266 | } 267 | 268 | function findPostBySlug(req, res) { 269 | 270 | } 271 | 272 | /** 273 | * updatePost 274 | * 275 | * updates a post in the Posts collection.
276 | * 277 | * Swagger sets req.swagger.params.id.value not req.params.id, see: 278 | * {@link https://github.com/apigee-127/swagger-tools/blob/master/docs/Middleware.md}

279 | * 280 | * Rule: PUT must be used to both insert and update a stored resource
281 | * Rule: PUT must be used to update mutable resources 282 | * 283 | * @public 284 | * @param {req} req - The HTTP request object. 285 | * @param {res} res - The HTTP response object. 286 | * @return {id} string - The unique id of the resource that was updated. 287 | * @see {@link http://expressjs.com/api.html#req} 288 | * @see {@link http://expressjs.com/api.html#res} 289 | */ 290 | function updatePost(req, res) { 291 | 292 | var id = req.swagger.params.id.value; 293 | 294 | // console.log('id: ' + id); 295 | 296 | var body = req.body; 297 | 298 | // console.log(util.inspect(body)); 299 | 300 | delete body.id; 301 | // make sure no one changes the author 302 | // delete body.author; 303 | 304 | // console.log(util.inspect(body)); 305 | 306 | res.type(APPLICATION_JSON); 307 | 308 | Post.findById(id) 309 | .exec(function(error, model) { 310 | if (! error) { 311 | 312 | if (null === model || undefined === model) 313 | { 314 | returnError(res, status.NOT_FOUND); 315 | } 316 | 317 | // console.log(util.inspect(model)); 318 | model = extend(model, body); 319 | // console.log(util.inspect(model)); 320 | 321 | model.save(function(error) { 322 | if (! error) { 323 | returnId(res, status.OK, model._id) ; 324 | } else { 325 | returnError(res, status.INTERNAL_SERVER_ERROR); 326 | } 327 | }); 328 | } else { 329 | returnError(res, status.NOT_FOUND); 330 | } 331 | }); 332 | } 333 | 334 | /** 335 | * deletePost 336 | * 337 | * deletes a post in the Posts collection.
338 | * 339 | * Swagger sets req.swagger.params.id.value not req.params.id, see: 340 | * {@link https://github.com/apigee-127/swagger-tools/blob/master/docs/Middleware.md}

341 | * 342 | * Rule: DELETE must be used to remove a resource from its parent 343 | * 344 | * @public 345 | * @param {req} req - The HTTP request object. 346 | * @param {res} res - The HTTP response object. 347 | * @return {id} string - The unique id of the resource that was deleted. 348 | * @see {@link http://expressjs.com/api.html#req} 349 | * @see {@link http://expressjs.com/api.html#res} 350 | */ 351 | function deletePost(req, res) { 352 | 353 | var id = req.swagger.params.id.value; 354 | 355 | // console.log('id: ' + id); 356 | 357 | res.type(APPLICATION_JSON); 358 | 359 | Post.findByIdAndRemove(id, function(error) { 360 | if (! error) { 361 | returnId(res, status.OK, id); 362 | } else { 363 | returnError(res, status.INTERNAL_SERVER_ERROR); 364 | } 365 | }); 366 | } 367 | 368 | function returnId(res, statusCode, objectId) { 369 | res.location(LOCATION + objectId); 370 | return res.status(statusCode).send(JSON.stringify({ id: objectId })); 371 | } 372 | 373 | function returnError(res, statusCode) { 374 | 375 | var errorMessage = 'Something went wrong :('; 376 | 377 | switch(statusCode) { 378 | 379 | case status.BAD_REQUEST: 380 | errorMessage = 'Bad request'; 381 | break; 382 | 383 | case status.NOT_FOUND: 384 | errorMessage = 'Resource not found'; 385 | break; 386 | 387 | case status.NOT_ACCEPTABLE: 388 | errorMessage = 'Not acceptable'; 389 | break; 390 | 391 | case status.INTERNAL_SERVER_ERROR: 392 | default: 393 | break; 394 | } 395 | 396 | return res.status(statusCode).send(JSON.stringify({ code: statusCode, message: errorMessage })); 397 | } 398 | 399 | module.exports = { 400 | addPost: addPost, 401 | findPosts: findPosts, 402 | findPostById: findPostById, 403 | // findPostBySlug: findPostBySlug, 404 | updatePost: updatePost, 405 | deletePost: deletePost 406 | } 407 | 408 | // ./node_modules/.bin/jsdoc /Users/robferguson/opt/WebStorm/projects/Vardyger/core/server/api/controllers/posts.js 409 | // ./node_modules/.bin/jsdoc /Users/robferguson/opt/WebStorm/projects/Vardyger/core/server/api/controllers/posts.js -t 410 | // ./node_modules/ink-docstrap/template -c ./node_modules/jsdoc/conf.json 411 | 412 | // http://themes.ghost.org/v0.6.4/docs/navigation 413 | // Ghost/core/server/controllers/frontend.js 414 | // Note: You can override the default template by placing a file called navigation.hbs in the partials directory 415 | // of your theme. 416 | 417 | /* 418 | 419 | // validateResponse: true, 420 | 421 | json: function(){ 422 | res.type(APPLICATION_JSON); 423 | res.status(status.OK).send(JSON.stringify( 424 | { 425 | id: model._id, 426 | title: model.title, 427 | slug: model.slug, 428 | markdown: model.markdown, 429 | html: model.html, 430 | image: model.image, 431 | featured: model.featured, 432 | page: model.page, 433 | state: model.state, 434 | locale: model.locale, 435 | metaTitle: model.metaTitle, 436 | metaDescription: model.metaDescription 437 | })); 438 | } 439 | 440 | */ 441 | -------------------------------------------------------------------------------- /core/server/api/mocks/README.md: -------------------------------------------------------------------------------- 1 | Place controllers for mock mode in this directory. 2 | -------------------------------------------------------------------------------- /core/server/api/mocks/post.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "The Vardyger publishing platform", 3 | "slug": "the-vardyger-publishing-platform", 4 | "markdown": "", 5 | "html": "In a previous post, I wrote about Swagger and how it can help you to model and build a RESTful API. In this post, I'll walk you through the steps required to create the API for the Vardyger publishing platform.", 6 | "image": "", 7 | "featured": false, 8 | "page": false, 9 | "state": "draft", 10 | "locale": "en_GB", 11 | "metaTitle": "The Vardyger publishing platform", 12 | "metaDescription": "In a previous post, ..." 13 | } -------------------------------------------------------------------------------- /core/server/api/models/post.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | var mongoose = require('mongoose'); 8 | 9 | var Schema = mongoose.Schema; 10 | 11 | /** 12 | * Post Schema 13 | */ 14 | 15 | var PostSchema = new Schema({ 16 | title: {type: String, required: true, trim: true}, 17 | slug: {type: String, required: true, trim: true}, 18 | markdown: {type: String, default: '', trim: true}, 19 | html: {type: String, default: '', trim: true}, 20 | image: {type: String, default: '', trim: true}, 21 | featured: {type: Boolean, default: false}, 22 | page: {type: Boolean, default: false}, 23 | state: { type: String, required: true, enum: ['draft', 'published'], default: 'draft'}, 24 | locale: {type: String, default: 'en_GB', trim: true}, 25 | metaTitle: {type: String, default: '', trim: true}, 26 | metaDescription: {type: String, default: '', trim: true}, 27 | 28 | // authorId: { type: Schema.ObjectId, ref: 'User' }, 29 | createdAt: { type: Date, default: Date.now }, 30 | // createdBy: { type: Schema.ObjectId, ref: 'User' }, 31 | updatedAt: { type: Date, default: Date.now }, 32 | // updatedBy: { type: Schema.ObjectId, ref: 'User' }, 33 | publishedAt: { type: Date, default: Date.now } 34 | // publishedBy: { type: Schema.ObjectId, ref: 'User' }, 35 | 36 | }); 37 | 38 | /** 39 | * Validations 40 | */ 41 | 42 | // PostSchema.path('title').required(true, 'Title cannot be blank'); 43 | // PostSchema.path('slug').required(true, 'Slug cannot be blank'); 44 | 45 | /** 46 | * Methods 47 | */ 48 | 49 | // PostSchema.methods = {} 50 | 51 | /** 52 | * Statics 53 | */ 54 | 55 | // PostSchema.statics = {} 56 | 57 | // module.exports = mongoose.model('Post', PostSchema); 58 | mongoose.model('Post', PostSchema); 59 | 60 | // To have the 'Post' model use the 'Post' collection, you need to explicitly provide that collection name as the 61 | // third parameter to mongoose.model, otherwise Mongoose will use the pluralised, lower-cased model name which 62 | // would be 'posts'. 63 | 64 | 65 | /* 66 | 67 | The term 'slug' comes from the world of newspaper production. 68 | 69 | It's an informal name given to a story during the production process. As the story winds its path from the beat 70 | reporter (assuming these even exist any more?) through to editor through to the "printing presses", this is the 71 | name it is referenced by, e.g., "Have you fixed those errors in the 'getting-started-with-node' story?". 72 | 73 | */ 74 | -------------------------------------------------------------------------------- /core/server/api/swagger/swagger.yaml: -------------------------------------------------------------------------------- 1 | swagger: '2.0' 2 | info: 3 | title: Vardyger API 4 | description: The RESTful API for the Vardyger publishing platform. 5 | version: '1.0.0' 6 | host: localhost:10010 7 | # host: api.vardyger.org 8 | basePath: /v1 9 | schemes: 10 | - http 11 | # - https 12 | consumes: 13 | - application/json 14 | produces: 15 | - application/json 16 | paths: 17 | /posts: 18 | x-swagger-router-controller: posts 19 | post: 20 | description: > 21 | Adds a post to the posts collection.
22 | Location (in the response header) is used to specify the URI of the newly created resource. 23 | operationId: addPost 24 | parameters: 25 | - name: post 26 | in: body 27 | description: The posts contents 28 | required: true 29 | schema: 30 | $ref: '#/definitions/Post' 31 | tags: 32 | - Posts 33 | produces: 34 | - application/json 35 | responses: 36 | 201: 37 | description: Created 38 | schema: 39 | $ref: '#/definitions/SuccessResponse' 40 | 500: 41 | description: Internal Server Error 42 | schema: 43 | $ref: '#/definitions/ErrorResponse' 44 | x-swagger-router-controller: posts 45 | get: 46 | description: > 47 | Returns all the posts in the collection. 48 | operationId: findPosts 49 | tags: 50 | - Posts 51 | produces: 52 | - application/json 53 | - text/html 54 | responses: 55 | 200: 56 | description: An array of posts 57 | schema: 58 | type: array 59 | items: 60 | $ref: '#/definitions/Post' 61 | 404: 62 | description: Not Found 63 | schema: 64 | $ref: '#/definitions/ErrorResponse' 65 | 406: 66 | description: Not Acceptable 67 | schema: 68 | $ref: '#/definitions/ErrorResponse' 69 | 500: 70 | description: Internal Server Error 71 | schema: 72 | $ref: '#/definitions/ErrorResponse' 73 | /posts/{id}: 74 | x-swagger-router-controller: posts 75 | get: 76 | description: Returns a post in the collection. 77 | operationId: findPostById 78 | parameters: 79 | - name: id 80 | in: path 81 | description: The posts ID 82 | required: true 83 | type: string 84 | tags: 85 | - Posts 86 | produces: 87 | - application/json 88 | - text/html 89 | responses: 90 | 200: 91 | description: A post 92 | schema: 93 | $ref: '#/definitions/Post' 94 | 404: 95 | description: Not Found 96 | schema: 97 | $ref: '#/definitions/ErrorResponse' 98 | 406: 99 | description: Not Acceptable 100 | schema: 101 | $ref: '#/definitions/ErrorResponse' 102 | 500: 103 | description: Internal Server Error 104 | schema: 105 | $ref: '#/definitions/ErrorResponse' 106 | x-swagger-router-controller: posts 107 | put: 108 | description: Updates a post in the posts collection. 109 | operationId: updatePost 110 | parameters: 111 | - name: id 112 | in: path 113 | description: The posts ID 114 | required: true 115 | type: string 116 | - name: post 117 | in: body 118 | description: The posts contents 119 | required: true 120 | schema: 121 | $ref: '#/definitions/Post' 122 | tags: 123 | - Posts 124 | produces: 125 | - application/json 126 | # - text/html 127 | responses: 128 | 200: 129 | description: OK 130 | schema: 131 | $ref: '#/definitions/SuccessResponse' 132 | 404: 133 | description: Not Found 134 | schema: 135 | $ref: '#/definitions/ErrorResponse' 136 | 500: 137 | description: Internal Server Error 138 | schema: 139 | $ref: '#/definitions/ErrorResponse' 140 | x-swagger-router-controller: posts 141 | delete: 142 | description: Deletes a post in the posts collection. 143 | operationId: deletePost 144 | parameters: 145 | - name: id 146 | in: path 147 | description: The posts ID 148 | required: true 149 | type: string 150 | tags: 151 | - Posts 152 | produces: 153 | - application/json 154 | # - text/html 155 | responses: 156 | 200: 157 | description: OK 158 | schema: 159 | $ref: '#/definitions/SuccessResponse' 160 | 404: 161 | description: Not Found 162 | schema: 163 | $ref: '#/definitions/ErrorResponse' 164 | 500: 165 | description: Internal Server Error 166 | schema: 167 | $ref: '#/definitions/ErrorResponse' 168 | definitions: 169 | Post: 170 | required: 171 | - title 172 | - markdown 173 | - html 174 | properties: 175 | id: 176 | type: string 177 | description: The posts unique identifier. 178 | title: 179 | type: string 180 | description: The posts title -> My First Blog Post. 181 | slug: 182 | type: string 183 | description: The posts slug -> my-first-blog-post. 184 | markdown: 185 | type: string 186 | description: The posts Markdown content. 187 | html: 188 | type: string 189 | description: The posts HTML content. 190 | image: 191 | type: string 192 | description: Associate a featured image with the post. 193 | featured: 194 | type: boolean 195 | description: Highlight this blog post. 196 | page: 197 | type: boolean 198 | description: Posts are listed in order from newest to oldest, pages are static and not listed by date. 199 | state: 200 | type: string 201 | description: The posts status -> draft. 202 | locale: 203 | type: string 204 | description: The posts (language and) locale -> en_GB. 205 | metaTitle: 206 | type: string 207 | description: Search Engine Optimsed (SEO) post title. 208 | metaDescription: 209 | type: string 210 | description: Search Engine Optimsed (SEO) post description. 211 | SuccessResponse: 212 | required: 213 | - id 214 | properties: 215 | id: 216 | type: string 217 | ErrorResponse: 218 | required: 219 | - code 220 | - message 221 | properties: 222 | code: 223 | type: integer 224 | message: 225 | type: string -------------------------------------------------------------------------------- /core/server/conf.docstrap.json: -------------------------------------------------------------------------------- 1 | { 2 | "tags": { 3 | "allowUnknownTags": true 4 | }, 5 | "plugins": ["plugins/markdown"], 6 | "templates": { 7 | "cleverLinks": false, 8 | "monospaceLinks": false, 9 | "dateFormat": "ddd MMM Do YYYY", 10 | "outputSourceFiles": true, 11 | "outputSourcePath": true, 12 | "systemName": "DocStrap", 13 | "footer": "", 14 | "copyright": "DocStrap Copyright © 2012-2014 The contributors to the JSDoc3 and DocStrap projects.", 15 | "navType": "vertical", 16 | "theme": "cerulean", 17 | "linenums": true, 18 | "collapseSymbols": false, 19 | "inverseNav": true, 20 | "highlightTutorialCode": true, 21 | "protocol": "html://" 22 | }, 23 | "markdown": { 24 | "parser": "gfm", 25 | "hardwrap": true 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /core/server/conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "tags": { 3 | "allowUnknownTags": true 4 | }, 5 | "source": { 6 | "includePattern": ".+\\.js(doc)?$", 7 | "excludePattern": "(^|\\/|\\\\)_" 8 | }, 9 | "plugins": [], 10 | "templates": { 11 | "cleverLinks": false, 12 | "monospaceLinks": false, 13 | "default": { 14 | "outputSourceFiles": true 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /core/server/config/README.md: -------------------------------------------------------------------------------- 1 | Place configuration files in this directory. 2 | -------------------------------------------------------------------------------- /core/server/config/default.yaml: -------------------------------------------------------------------------------- 1 | # swagger configuration file 2 | 3 | # values in the swagger hash are system configuration for swagger 4 | swagger: 5 | mapErrorsToJson: true 6 | docEndpoints: 7 | raw: /swagger 8 | 9 | # any other values in this file are just loaded into the config for application access... 10 | -------------------------------------------------------------------------------- /core/server/helpers/README.md: -------------------------------------------------------------------------------- 1 | Place helper files in this directory. 2 | -------------------------------------------------------------------------------- /core/server/helpers/asset.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Module dependencies 5 | */ 6 | 7 | var hbs = require('express-hbs'); 8 | 9 | function asset(name) { 10 | 11 | var output = ''; 12 | 13 | output = '/assets/' + name; 14 | 15 | return new hbs.handlebars.SafeString(output); 16 | } 17 | 18 | module.exports = asset; -------------------------------------------------------------------------------- /core/server/helpers/author.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Module dependencies 5 | */ 6 | 7 | var hbs = require('express-hbs'), 8 | _ = require('lodash'); 9 | 10 | function author(context, options) { 11 | 12 | var output = ''; 13 | 14 | if (this.author.name) { 15 | output = _.escape(this.author.name); 16 | } 17 | 18 | return new hbs.handlebars.SafeString(output); 19 | } 20 | 21 | module.exports = author; -------------------------------------------------------------------------------- /core/server/helpers/body_class.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Module dependencies 5 | */ 6 | 7 | var hbs = require('express-hbs'); 8 | 9 | function body_class(options) { 10 | 11 | var output = 'post-template tag-express-js tag-swagger tag-vardyger'; 12 | 13 | return new hbs.handlebars.SafeString(output); 14 | } 15 | 16 | module.exports = body_class; -------------------------------------------------------------------------------- /core/server/helpers/content.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Module dependencies 5 | */ 6 | 7 | var hbs = require('express-hbs'); 8 | 9 | function content(options) { 10 | return new hbs.handlebars.SafeString(this.html || ''); 11 | } 12 | 13 | module.exports = content; 14 | 15 | // downsize = Tag-safe truncation for HTML and XML. Works by word! -------------------------------------------------------------------------------- /core/server/helpers/date.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Module dependencies 5 | */ 6 | 7 | var moment = require('moment'); 8 | 9 | function date(context, options) { 10 | 11 | var output = ''; 12 | 13 | context = context === null ? undefined : context; 14 | 15 | output = moment(context).fromNow(); 16 | 17 | return output; 18 | } 19 | 20 | module.exports = date; -------------------------------------------------------------------------------- /core/server/helpers/encode.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Module dependencies 5 | */ 6 | var hbs = require('express-hbs'); 7 | 8 | function encode(context, str) { 9 | 10 | var uri = context || str; 11 | 12 | return new hbs.handlebars.SafeString(encodeURIComponent(uri)); 13 | } 14 | 15 | module.exports = encode; -------------------------------------------------------------------------------- /core/server/helpers/excerpt.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Module dependencies 5 | */ 6 | 7 | var hbs = require('express-hbs'), 8 | downsize = require('downsize'); 9 | 10 | function excerpt(options) { 11 | 12 | var truncateOptions = (options || {}).hash || {}, 13 | excerpt; 14 | 15 | excerpt = String(this.html); 16 | 17 | // Strip inline and bottom footnotes 18 | excerpt = excerpt.replace(/.*?<\/a>/gi, ''); 19 | excerpt = excerpt.replace(/
    .*?<\/ol><\/div>/, ''); 20 | 21 | // Strip other html 22 | excerpt = excerpt.replace(/<\/?[^>]+>/gi, ''); 23 | excerpt = excerpt.replace(/(\r\n|\n|\r)+/gm, ' '); 24 | 25 | if (!truncateOptions.words && !truncateOptions.characters) { 26 | truncateOptions.words = 50; 27 | } 28 | 29 | return new hbs.handlebars.SafeString(downsize(excerpt, truncateOptions)); 30 | } 31 | 32 | module.exports = excerpt; 33 | 34 | // downsize = Tag-safe truncation for HTML and XML. Works by word! -------------------------------------------------------------------------------- /core/server/helpers/foreach.js: -------------------------------------------------------------------------------- 1 | // # Foreach Helper 2 | // Usage: `{{#foreach data}}{{/foreach}}` 3 | // 4 | // Block helper designed for looping through posts 5 | 6 | var hbs = require('express-hbs'), 7 | foreach; 8 | 9 | foreach = function (context, options) { 10 | var fn = options.fn, 11 | inverse = options.inverse, 12 | i = 0, 13 | j = 0, 14 | columns = options.hash.columns, 15 | key, 16 | ret = '', 17 | data; 18 | 19 | if (options.data) { 20 | data = hbs.handlebars.createFrame(options.data); 21 | } 22 | 23 | function setKeys(_data, _i, _j, _columns) { 24 | if (_i === 0) { 25 | _data.first = true; 26 | } 27 | if (_i === _j - 1) { 28 | _data.last = true; 29 | } 30 | // first post is index zero but still needs to be odd 31 | if (_i % 2 === 1) { 32 | _data.even = true; 33 | } else { 34 | _data.odd = true; 35 | } 36 | if (_i % _columns === 0) { 37 | _data.rowStart = true; 38 | } else if (_i % _columns === (_columns - 1)) { 39 | _data.rowEnd = true; 40 | } 41 | return _data; 42 | } 43 | if (context && typeof context === 'object') { 44 | if (context instanceof Array) { 45 | for (j = context.length; i < j; i += 1) { 46 | if (data) { 47 | data.index = i; 48 | data.first = data.rowEnd = data.rowStart = data.last = data.even = data.odd = false; 49 | data = setKeys(data, i, j, columns); 50 | } 51 | ret = ret + fn(context[i], {data: data}); 52 | } 53 | } else { 54 | for (key in context) { 55 | if (context.hasOwnProperty(key)) { 56 | j += 1; 57 | } 58 | } 59 | for (key in context) { 60 | if (context.hasOwnProperty(key)) { 61 | if (data) { 62 | data.key = key; 63 | data.first = data.rowEnd = data.rowStart = data.last = data.even = data.odd = false; 64 | data = setKeys(data, i, j, columns); 65 | } 66 | ret = ret + fn(context[key], {data: data}); 67 | i += 1; 68 | } 69 | } 70 | } 71 | } 72 | 73 | if (i === 0) { 74 | ret = inverse(this); 75 | } 76 | 77 | return ret; 78 | }; 79 | 80 | module.exports = foreach; -------------------------------------------------------------------------------- /core/server/helpers/ghost_foot.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Module dependencies 5 | */ 6 | 7 | var hbs = require('express-hbs'); 8 | 9 | function ghost_foot(options) { 10 | 11 | // 12 | 13 | var output = ''; 14 | 15 | return new hbs.handlebars.SafeString(output); 16 | } 17 | 18 | module.exports = ghost_foot; 19 | 20 | // TODO: revisit ghost_foot -------------------------------------------------------------------------------- /core/server/helpers/ghost_head.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Module dependencies 5 | */ 6 | 7 | var hbs = require('express-hbs'); 8 | 9 | function ghost_head(options) { 10 | 11 | var output = ''; 12 | 13 | return new hbs.handlebars.SafeString(output); 14 | } 15 | 16 | module.exports = ghost_head; 17 | 18 | // TODO: revisit ghost_head 19 | 20 | // head.push(''); 21 | // head.push(''); 22 | // -------------------------------------------------------------------------------- /core/server/helpers/has.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Module dependencies 5 | */ 6 | 7 | function has(options) { 8 | 9 | return false; 10 | } 11 | 12 | module.exports = has; 13 | 14 | // TODO: revisit has -------------------------------------------------------------------------------- /core/server/helpers/image.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Module dependencies 5 | */ 6 | 7 | var hbs = require('express-hbs'); 8 | 9 | function image(options) { 10 | 11 | var output = ''; 12 | 13 | return new hbs.handlebars.SafeString(output); 14 | } 15 | 16 | module.exports = image; 17 | 18 | // TODO: revisit im image.js -------------------------------------------------------------------------------- /core/server/helpers/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Module dependencies 5 | * If a module is a directory, the file in the module directory that will be evaluated must be named index.js 6 | */ 7 | 8 | var hbs = require('express-hbs'), 9 | coreHelpers = {}; 10 | 11 | coreHelpers.asset = require('./asset'); 12 | coreHelpers.author = require('./author'); 13 | coreHelpers.body_class = require('./body_class'); 14 | coreHelpers.content = require('./content'); 15 | coreHelpers.date = require('./date'); 16 | coreHelpers.encode = require('./encode'); 17 | coreHelpers.excerpt = require('./excerpt'); 18 | coreHelpers.foreach = require('./foreach'); 19 | coreHelpers.ghost_foot = require('./ghost_foot'); 20 | coreHelpers.ghost_head = require('./ghost_head'); 21 | coreHelpers.image = require('./image'); 22 | // coreHelpers.is = require('./is'); 23 | coreHelpers.has = require('./has'); 24 | coreHelpers.meta_description = require('./meta_description'); 25 | coreHelpers.meta_title = require('./meta_title'); 26 | coreHelpers.navigation = require('./navigation'); 27 | // coreHelpers.pagination = require('./pagination'); 28 | // coreHelpers.plural = require('./plural'); 29 | coreHelpers.post_class = require('./post_class'); 30 | // coreHelpers.prev_post = require('./prev_next'); 31 | // coreHelpers.next_post = require('./prev_next'); 32 | coreHelpers.tags = require('./tags'); 33 | coreHelpers.title = require('./title'); 34 | coreHelpers.url = require('./url'); 35 | 36 | // Specialist helpers for certain templates 37 | // coreHelpers.input_password = require('./input_password'); 38 | // coreHelpers.page_url = require('./page_url'); 39 | // coreHelpers.pageUrl = require('./page_url').deprecated; 40 | 41 | coreHelpers.helperMissing = function (arg) { 42 | if (arguments.length === 2) { 43 | return undefined; 44 | } 45 | 46 | // errors.logError('Missing helper: "' + arg + '"'); 47 | console.log('Missing helper: "' + arg + '"'); 48 | }; 49 | 50 | function registerThemeHelperSync(name, fn) { 51 | hbs.registerHelper(name, fn); 52 | } 53 | 54 | function registerHelpers() { 55 | registerThemeHelperSync('asset', coreHelpers.asset); 56 | registerThemeHelperSync('author', coreHelpers.author); 57 | registerThemeHelperSync('body_class', coreHelpers.body_class); 58 | registerThemeHelperSync('content', coreHelpers.content); 59 | registerThemeHelperSync('date', coreHelpers.date); 60 | registerThemeHelperSync('encode', coreHelpers.encode); 61 | registerThemeHelperSync('excerpt', coreHelpers.excerpt); 62 | registerThemeHelperSync('foreach', coreHelpers.foreach); 63 | registerThemeHelperSync('ghost_foot', coreHelpers.ghost_foot); 64 | registerThemeHelperSync('ghost_head', coreHelpers.ghost_head); 65 | registerThemeHelperSync('image', coreHelpers.image); 66 | registerThemeHelperSync('has', coreHelpers.has); 67 | registerThemeHelperSync('meta_description', coreHelpers.meta_description); 68 | registerThemeHelperSync('meta_title', coreHelpers.meta_title); 69 | registerThemeHelperSync('navigation', coreHelpers.navigation); 70 | registerThemeHelperSync('post_class', coreHelpers.post_class); 71 | registerThemeHelperSync('tags', coreHelpers.tags); 72 | registerThemeHelperSync('title', coreHelpers.title); 73 | registerThemeHelperSync('url', coreHelpers.url); 74 | } 75 | 76 | module.exports = coreHelpers; 77 | module.exports.loadCoreHelpers = registerHelpers; 78 | module.exports.registerThemeHelperSync = registerThemeHelperSync; 79 | -------------------------------------------------------------------------------- /core/server/helpers/meta_description.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Module dependencies 5 | */ 6 | 7 | var hbs = require('express-hbs'), 8 | _ = require('lodash'); 9 | 10 | function meta_description(context, options) { 11 | 12 | var output = ''; 13 | 14 | if (this.meta_description) { 15 | output = _.escape(this.meta_description); 16 | } 17 | 18 | return new hbs.handlebars.SafeString(output); 19 | } 20 | 21 | module.exports = meta_description; -------------------------------------------------------------------------------- /core/server/helpers/meta_title.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Module dependencies 5 | */ 6 | 7 | var hbs = require('express-hbs'), 8 | _ = require('lodash'); 9 | 10 | function meta_title(context, options) { 11 | 12 | var output = ''; 13 | 14 | if (this.meta_title) { 15 | output = _.escape(this.meta_title); 16 | } 17 | 18 | return new hbs.handlebars.SafeString(output); 19 | } 20 | 21 | module.exports = meta_title; -------------------------------------------------------------------------------- /core/server/helpers/navigation.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Module dependencies 5 | */ 6 | 7 | var hbs = require('express-hbs'), 8 | _ = require('lodash'), 9 | template = require('./template'); 10 | 11 | function navigation(options) { 12 | 13 | var navigationData = options.data.blog.navigation, 14 | output, 15 | context; 16 | 17 | if (!_.isObject(navigationData) || _.isFunction(navigationData)) { 18 | // return errors.logAndThrowError('navigation data is not an object or is a function'); 19 | return new hbs.handlebars.SafeString(''); 20 | } 21 | 22 | // {{navigation}} should no-op if no data is passed in 23 | if (navigationData.length === 0) { 24 | // return new hbs.SafeString(''); 25 | return new hbs.handlebars.SafeString(''); 26 | } 27 | 28 | output = navigationData.map(function (e) { 29 | var out = {}; 30 | // out.current = e.url === currentUrl; 31 | out.current = false; 32 | out.label = e.label; 33 | out.slug = _slugify(e.label); 34 | out.url = hbs.handlebars.Utils.escapeExpression(e.url); 35 | return out; 36 | }); 37 | 38 | context = _.merge({}, {navigation: output}); 39 | 40 | return template.execute('navigation', context, options); 41 | } 42 | 43 | module.exports = navigation; 44 | 45 | // currentUrl = options.data.root.relativeUrl, -------------------------------------------------------------------------------- /core/server/helpers/post_class.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Module dependencies 5 | */ 6 | 7 | var hbs = require('express-hbs'); 8 | 9 | function post_class(options) { 10 | 11 | var output = 'post tag-express-js tag-swagger tag-vardyger'; 12 | 13 | return new hbs.handlebars.SafeString(output); 14 | } 15 | 16 | module.exports = post_class; -------------------------------------------------------------------------------- /core/server/helpers/tags.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Module dependencies 5 | */ 6 | 7 | var hbs = require('express-hbs'); 8 | 9 | function tags(options) { 10 | 11 | var output = ''; 12 | 13 | return new hbs.handlebars.SafeString(output); 14 | } 15 | 16 | module.exports = tags; -------------------------------------------------------------------------------- /core/server/helpers/template.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Module dependencies 5 | */ 6 | 7 | var hbs = require('express-hbs'); 8 | 9 | // Execute a template helper 10 | // All template helpers are registered as partial views. 11 | 12 | function execute(name, context, options) { 13 | 14 | var partial = hbs.handlebars.partials[name]; 15 | 16 | if (partial === undefined) { 17 | // errors.logAndThrowError('Template ' + name + ' not found.'); 18 | console.log('partial === undefined'); 19 | return; 20 | } 21 | 22 | // If the partial view is not compiled, it compiles and saves in handlebars 23 | if (typeof partial === 'string') { 24 | hbs.registerPartial(partial); 25 | } 26 | 27 | return new hbs.handlebars.SafeString(partial(context, options)); 28 | } 29 | 30 | module.exports = { 31 | execute: execute 32 | } -------------------------------------------------------------------------------- /core/server/helpers/title.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Module dependencies 5 | * If a module is a directory, the file in the module directory that will be evaluated must be named index.js 6 | */ 7 | 8 | // Overrides the standard behaviour of `{[title}}` to ensure the content is correctly escaped 9 | 10 | var hbs = require('express-hbs'); 11 | 12 | function title(options) { 13 | return new hbs.handlebars.SafeString(hbs.handlebars.Utils.escapeExpression(this.title || '')); 14 | } 15 | 16 | module.exports = title; -------------------------------------------------------------------------------- /core/server/helpers/url.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Module dependencies 5 | */ 6 | 7 | var hbs = require('express-hbs'); 8 | 9 | function url(name) { 10 | 11 | var output = ''; 12 | 13 | output = '/post'; 14 | 15 | return output; 16 | } 17 | 18 | module.exports = url; -------------------------------------------------------------------------------- /core/server/middleware/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Module dependencies 5 | * If a module is a directory, the file in the module directory that will be evaluated must be named index.js 6 | */ 7 | var hbs = require('express-hbs'); 8 | 9 | function configHbsForContext(req, res, next) { 10 | 11 | // var themeData = config.theme; 12 | 13 | var themeData = { title: 'Blog Title', description: 'Blog Description'}; 14 | 15 | hbs.updateTemplateOptions({data: {blog: themeData}}); 16 | 17 | next(); 18 | } 19 | 20 | function setupMiddleware(app) { 21 | app.use(configHbsForContext); 22 | } 23 | 24 | module.exports = setupMiddleware; 25 | // module.exports.middleware = setupMiddleware; -------------------------------------------------------------------------------- /core/server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Vardyger", 3 | "version": "1.0.0", 4 | "description": "The Vardyger Publishing Platform :)", 5 | "author": "The Vardyger Foundation", 6 | "homepage": "http://vardyger.org", 7 | "keywords": [ 8 | "vardyger", 9 | "swagger", 10 | "swagger-tools", 11 | "express", 12 | "mongoose", 13 | "mongodb", 14 | "passport", 15 | "restful", 16 | "api", 17 | "blog", 18 | "cms" 19 | ], 20 | "repository": { 21 | "type": "git", 22 | "url": "https://github.com/Robinyo/Vardyger.git" 23 | }, 24 | "bugs": "https://github.com/Robinyo/Vardyger/issues", 25 | "license": "MIT", 26 | "main": "server.js", 27 | "scripts": { 28 | "start": "node --harmony server" 29 | }, 30 | "engines": { 31 | "node": "~0.12.0", 32 | "iojs": "~1.2.0" 33 | }, 34 | "dependencies": { 35 | "body-parser": "^1.12.4", 36 | "cors": "^2.7.1", 37 | "downsize": "0.0.8", 38 | "errorhandler": "^1.4.0", 39 | "express": "^4.12.3", 40 | "express-hbs": "^0.8.4", 41 | "i18n": "^0.5.0", 42 | "lodash": "^3.9.3", 43 | "method-override": "^2.3.3", 44 | "moment": "^2.10.3", 45 | "mongoose": "^4.0.5", 46 | "morgan": "^1.5.3", 47 | "serve-favicon": "^2.3.0", 48 | "swagger-express-mw": "0.0.x", 49 | "swagger-tools": "^0.8.7" 50 | }, 51 | "devDependencies": { 52 | "should": "^5.2.0", 53 | "supertest": "^0.15.0" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /core/server/public/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/server/public/images/favicon.ico -------------------------------------------------------------------------------- /core/server/server.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Vardyger 3 | * Copyright(c) 2015 Rob Ferguson 4 | * MIT Licensed 5 | */ 6 | 7 | 'use strict'; 8 | 9 | /** 10 | * Module dependencies. 11 | * @private 12 | */ 13 | 14 | var fs = require('fs'), 15 | path = require('path'), 16 | 17 | swagger = require('swagger-express-mw'), 18 | SwaggerUi = require('swagger-tools/middleware/swagger-ui'), 19 | 20 | express = require('express'), 21 | hbs = require('express-hbs'), 22 | helpers = require('./helpers'), 23 | middleware = require('./middleware'), 24 | mongoose = require('mongoose'), 25 | 26 | logger = require('morgan'), 27 | methodOverride = require('method-override'), 28 | bodyParser = require('body-parser'), 29 | errorHandler = require('errorhandler'); 30 | 31 | var app = express(); 32 | 33 | app.set('port', process.env.PORT || 10010); 34 | 35 | var config = { 36 | appRoot: __dirname, 37 | validateResponse: false, // how to support json or html response ??? 38 | db: 'mongodb://localhost/vardyger-dev', 39 | theme: 'casper' // casper goblin ... 40 | }; 41 | 42 | // e.g., /content/themes/casper 43 | var themeDir = path.resolve(__dirname + '../../../content/themes/' + config.theme); 44 | // /core (shared) 45 | var sharedDir = path.resolve(__dirname + '../../'); 46 | // Layouts are in the theme directory 47 | // var layoutsDir = themeDir; 48 | 49 | app.engine('hbs', hbs.express4({ 50 | layoutsDir: themeDir, 51 | defaultLayout: themeDir + '/default.hbs', 52 | partialsDir: themeDir + '/partials' 53 | // i18n: 54 | })); 55 | app.set('view engine', 'hbs'); 56 | app.set('views', themeDir); 57 | app.set('view cache', false); 58 | 59 | helpers.loadCoreHelpers(); 60 | 61 | // middleware(blogApp, adminApp); 62 | // middleware.setupMiddleware(app); 63 | // https://github.com/TryGhost/Ghost/blob/master/core/server/middleware/index.js#L91 64 | 65 | var url = 'http://robferguson.org'; 66 | // var url = 'http://localhost:10010'; 67 | 68 | var themeData = { 69 | title: 'Rob Ferguson', 70 | description: 'Blog Description', 71 | url: url, 72 | navigation: true 73 | }; 74 | 75 | hbs.updateTemplateOptions({data: {blog: themeData}}); 76 | 77 | var connect = function () { 78 | var options = { server: { socketOptions: { keepAlive: 1 } } }; 79 | mongoose.connect(config.db, options); 80 | }; 81 | connect(); 82 | 83 | mongoose.connection.on('error', console.log); 84 | // mongoose.connection.on('disconnected', connect); 85 | 86 | // Bootstrap mongoose models 87 | fs.readdirSync(__dirname + '/api/models').forEach(function (file) { 88 | if (~file.indexOf('.js')) require(__dirname + '/api/models/' + file); 89 | }); 90 | 91 | swagger.create(config, function(err, swaggerExpress) { 92 | 93 | if (err) { throw err; } 94 | 95 | app.use(SwaggerUi(swaggerExpress.runner.swagger)); 96 | 97 | app.use(logger('dev')); 98 | app.use(methodOverride()); 99 | // app.use(session({ resave: true, saveUninitialized: true, secret: 'uwotm8' })); 100 | app.use(bodyParser.json()); 101 | app.use(bodyParser.urlencoded({extended: false})); 102 | // app.use(multer()); 103 | 104 | // TODO: revisit server.js 105 | // http://stackoverflow.com/questions/18310394/no-access-control-allow-origin-node-apache-port-issue 106 | // app.use(require('cors')()); 107 | 108 | app.use(express.static(sharedDir)); 109 | app.use(express.static(themeDir)); 110 | // console.log('express.static: ' + sharedDir); 111 | // console.log('express.static: ' + themeDir); 112 | 113 | // global.blog = { title: 'Title', description: 'Description' }; 114 | // console.log('global.blog.title: ' + global.blog.title); 115 | 116 | // error handling middleware should be loaded after loading routes 117 | if ('development' == app.get('env')) { 118 | app.use(errorHandler()); 119 | } 120 | 121 | swaggerExpress.register(app); 122 | 123 | app.listen(app.get('port')); 124 | }); 125 | 126 | module.exports = app; 127 | 128 | /* 129 | 130 | // https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md 131 | // https://github.com/apigee-127/swagger-tools/blob/master/docs/Middleware.md 132 | 133 | // DEBUG=swagger-tools:middleware:* node 134 | 135 | // cd ~/opt/WebStorm/projects/Vardyger/core/server 136 | // swagger project start 137 | // swagger project edit 138 | // http://localhost:10010/docs 139 | 140 | ulimit -n 1024 && mongod --config /usr/local/etc/mongod.conf 141 | 142 | ... 143 | 144 | mongo 145 | show dbs 146 | use vardyger-dev 147 | show collections 148 | 149 | db.posts.find() 150 | db.posts.drop() 151 | 152 | exit 153 | 154 | */ -------------------------------------------------------------------------------- /core/server/test/api/controllers/README.md: -------------------------------------------------------------------------------- 1 | Place your controller tests in this directory. 2 | -------------------------------------------------------------------------------- /core/server/test/api/controllers/hello_world.js: -------------------------------------------------------------------------------- 1 | var should = require('should'); 2 | var request = require('supertest'); 3 | var server = require('../../../app'); 4 | 5 | process.env.A127_ENV = 'test'; 6 | 7 | describe('controllers', function() { 8 | 9 | describe('hello_world', function() { 10 | 11 | describe('GET /hello', function() { 12 | 13 | it('should return a default string', function(done) { 14 | 15 | request(server) 16 | .get('/hello') 17 | .set('Accept', 'application/json') 18 | .expect('Content-Type', /json/) 19 | .expect(200) 20 | .end(function(err, res) { 21 | should.not.exist(err); 22 | 23 | res.body.should.eql('Hello, stranger!'); 24 | 25 | done(); 26 | }); 27 | }); 28 | 29 | it('should accept a name parameter', function(done) { 30 | 31 | request(server) 32 | .get('/hello') 33 | .query({ name: 'Scott'}) 34 | .set('Accept', 'application/json') 35 | .expect('Content-Type', /json/) 36 | .expect(200) 37 | .end(function(err, res) { 38 | should.not.exist(err); 39 | 40 | res.body.should.eql('Hello, Scott!'); 41 | 42 | done(); 43 | }); 44 | }); 45 | 46 | }); 47 | 48 | }); 49 | 50 | }); 51 | -------------------------------------------------------------------------------- /core/server/test/api/helpers/README.md: -------------------------------------------------------------------------------- 1 | Place your helper tests in this directory. 2 | -------------------------------------------------------------------------------- /core/server/utils/http-status-codes.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | 5 | OK: 200, // Indicates a nonspecific success 6 | CREATED: 201, // Sent primarily by collections and stores but sometimes also by controllers, 7 | // to indicate that a new resource has been created 8 | ACCEPTED: 202, // Sent by controllers to indicate the start of an asynchronous action 9 | NO_CONTENT: 204, // Indicates that the body has been intentionally left blank 10 | MOVED_PERMANENTLY: 301, // Indicates that a new permanent URI has been assigned to the client’s requested resource 11 | NOT_MODIFIED: 304, // Sent to preserve bandwidth (with conditional GET) 12 | TEMPORARY_REDIRECT: 307, // Indicates that a temporary URI has been assigned to the client’s requested resource 13 | BAD_REQUEST: 400, // Indicates a nonspecific client error 14 | UNAUTHORISED: 401, // Sent when the client either provided invalid credentials or forgot to send them 15 | FORBIDDEN: 403, // Used to forbid access regardless of authorisation state 16 | NOT_FOUND: 404, // Sent when the client tried to interact with a URI that the REST API could not map to a resource 17 | METHOD_NOT_ALLOWED: 405, // Sent when the client tried to interact using an unsupported HTTP method 18 | NOT_ACCEPTABLE: 406, // Sent when the client tried to request data in an unsupported media type format 19 | UNSUPPORTED_MEDIA_TYPE: 415, // Sent when the client submitted data in an unsupported media type format 20 | INTERNAL_SERVER_ERROR: 500 // Tells the client that the API is having problems of its own 21 | 22 | }; -------------------------------------------------------------------------------- /core/shared/favicon.ico: -------------------------------------------------------------------------------- 1 |  ((  0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @0, @ -------------------------------------------------------------------------------- /core/shared/img/user-cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/shared/img/user-cover.png -------------------------------------------------------------------------------- /core/shared/img/user-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Robinyo/Vardyger/f04cc2cf1a86296c61e82d4dfb38e8ade9912c13/core/shared/img/user-image.png -------------------------------------------------------------------------------- /core/shared/private-robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: / -------------------------------------------------------------------------------- /core/shared/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Sitemap: {{blog-url}}/sitemap.xml 3 | Disallow: /ghost/ 4 | -------------------------------------------------------------------------------- /core/shared/sitemap.xsl: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | XML Sitemap 12 | 13 | 65 | 66 | 67 |
    68 |

    XML Sitemap

    69 |

    70 | This is a sitemap generated by Ghost to allow search engines to discover this blog's content. 71 |

    72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 89 | 92 | 93 | 94 | 95 |
    SitemapLast Modified
    87 | 88 | 90 | 91 |
    96 |
    97 | 98 |

    ← Back to index

    99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 122 | 125 | 128 | 131 | 134 | 135 | 136 | 137 |
    URL ( total)PrioImagesCh. Freq.Last Modified
    115 | 116 | 117 | 118 | 119 | 120 | 121 | 123 | 124 | 126 | 127 | 129 | 130 | 132 | 133 |
    138 |

    ← Back to index

    139 |
    140 |
    141 | 142 | 143 | 144 | 145 | --------------------------------------------------------------------------------