├── client ├── vendor │ └── .gitkeep ├── app │ ├── helpers │ │ ├── .gitkeep │ │ ├── repeat-text.js │ │ └── output-value.js │ ├── models │ │ ├── .gitkeep │ │ ├── tag.js │ │ ├── project.js │ │ └── post.js │ ├── routes │ │ ├── .gitkeep │ │ ├── 404.js │ │ ├── auth.js │ │ ├── stream.js │ │ ├── auth │ │ │ └── login.js │ │ ├── about.js │ │ ├── blog-posts │ │ │ ├── tag-filtered.js │ │ │ ├── posts-list.js │ │ │ ├── posts-list-page.js │ │ │ ├── post-edit.js │ │ │ ├── post-new.js │ │ │ └── post-read.js │ │ ├── projects.js │ │ ├── application.js │ │ ├── blog-posts.js │ │ └── projects │ │ │ ├── list.js │ │ │ └── create.js │ ├── components │ │ ├── .gitkeep │ │ ├── tags-list.js │ │ ├── admin-toolbar.js │ │ ├── lctv-frame.js │ │ ├── blog-post-body.js │ │ ├── nav-bar.js │ │ ├── image-uploader.js │ │ ├── project-edit-form.js │ │ ├── autocomplete-input.js │ │ └── post-edit-form.js │ ├── controllers │ │ ├── .gitkeep │ │ ├── projects.js │ │ ├── application.js │ │ ├── stream.js │ │ ├── auth │ │ │ └── login.js │ │ └── blog-posts.js │ ├── styles │ │ ├── _projects.scss │ │ ├── blog-posts │ │ │ ├── _post-new.scss │ │ │ ├── _post-read.scss │ │ │ └── _posts-list.scss │ │ ├── _helpers.scss │ │ ├── components │ │ │ ├── _lctv-frame.scss │ │ │ ├── _tags-list.scss │ │ │ ├── _image-uploader.scss │ │ │ ├── _autocomplete-input.scss │ │ │ ├── _admin-toolbar.scss │ │ │ ├── _post-edit-form.scss │ │ │ ├── _blog-post-body.scss │ │ │ └── _nav-bar.scss │ │ ├── _mixins.scss │ │ ├── _about.scss │ │ ├── auth │ │ │ └── _login.scss │ │ ├── _bits.scss │ │ ├── _a2a.scss │ │ ├── app.scss │ │ ├── _application.scss │ │ ├── _generic.scss │ │ └── _media-queries.scss │ ├── templates │ │ ├── auth.hbs │ │ ├── projects.hbs │ │ ├── stream.hbs │ │ ├── blog-posts.hbs │ │ ├── components │ │ │ ├── blog-post-body.hbs │ │ │ ├── admin-toolbar.hbs │ │ │ ├── tags-list.hbs │ │ │ ├── lctv-frame.hbs │ │ │ ├── autocomplete-input.hbs │ │ │ ├── image-uploader.hbs │ │ │ ├── nav-bar.hbs │ │ │ ├── project-edit-form.hbs │ │ │ └── post-edit-form.hbs │ │ ├── blog-posts │ │ │ ├── post-new.hbs │ │ │ ├── post-edit.hbs │ │ │ ├── tag-filtered.hbs │ │ │ ├── posts-list.hbs │ │ │ └── post-read.hbs │ │ ├── projects │ │ │ ├── create.hbs │ │ │ └── list.hbs │ │ ├── head.hbs │ │ ├── 404.hbs │ │ ├── application.hbs │ │ ├── auth │ │ │ └── login.hbs │ │ └── about.hbs │ ├── resolver.js │ ├── authorizers │ │ └── oauth2.js │ ├── serializers │ │ ├── application.js │ │ ├── tag.js │ │ └── post.js │ ├── authenticators │ │ └── oauth2.js │ ├── storages │ │ └── post-backup.js │ ├── adapters │ │ └── application.js │ ├── app.js │ ├── initializers │ │ ├── scroll-reset.js │ │ ├── reset-navbar.js │ │ └── nav-indicator.js │ ├── services │ │ ├── lctv.js │ │ ├── user.js │ │ └── api.js │ ├── index.html │ └── router.js ├── tests │ ├── unit │ │ ├── .gitkeep │ │ ├── helpers │ │ │ ├── repeat-test.js │ │ │ ├── repeat-text-test.js │ │ │ └── output-value-test.js │ │ ├── routes │ │ │ ├── 404-test.js │ │ │ ├── about-test.js │ │ │ ├── auth-test.js │ │ │ ├── stream-test.js │ │ │ ├── projects-test.js │ │ │ ├── auth │ │ │ │ └── login-test.js │ │ │ ├── blog-posts-test.js │ │ │ ├── projects │ │ │ │ ├── list-test.js │ │ │ │ └── create-test.js │ │ │ └── blog-posts │ │ │ │ ├── post-edit-test.js │ │ │ │ ├── post-new-test.js │ │ │ │ ├── post-read-test.js │ │ │ │ ├── posts-list-test.js │ │ │ │ └── tag-filtered-test.js │ │ ├── models │ │ │ ├── tag-test.js │ │ │ └── post-test.js │ │ ├── services │ │ │ ├── api-test.js │ │ │ └── user-test.js │ │ ├── adapters │ │ │ └── application-test.js │ │ ├── controllers │ │ │ ├── projects-test.js │ │ │ ├── application-test.js │ │ │ ├── auth │ │ │ │ └── login-test.js │ │ │ └── blog-posts-test.js │ │ └── initializers │ │ │ ├── nav-indicator-test.js │ │ │ └── webfont-loader-test.js │ ├── integration │ │ ├── .gitkeep │ │ └── components │ │ │ ├── blog-post-body-test.js │ │ │ ├── lctv-frame-test.js │ │ │ ├── tags-list-test.js │ │ │ ├── image-uploader-test.js │ │ │ ├── project-edit-form-test.js │ │ │ ├── autocomplete-input-test.js │ │ │ ├── admin-toolbar-test.js │ │ │ ├── nav-bar-test.js │ │ │ └── post-edit-form-test.js │ ├── test-helper.js │ ├── helpers │ │ ├── destroy-app.js │ │ ├── resolver.js │ │ ├── start-app.js │ │ └── module-for-acceptance.js │ ├── .jshintrc │ └── index.html ├── server │ ├── .jshintrc │ ├── index.js │ └── mocks │ │ └── posts.js ├── .watchmanconfig ├── public │ ├── robots.txt │ └── crossdomain.xml ├── .bowerrc ├── testem.json ├── testem.js ├── .ember-cli ├── .gitignore ├── .editorconfig ├── .travis.yml ├── bower.json ├── .jshintrc ├── config │ ├── deploy.js │ └── environment.js ├── ember-cli-build.js ├── README.md └── package.json ├── cache ├── .jshintrc ├── package.json ├── phantom.js ├── bin │ └── www └── app.js ├── server ├── .jshintrc ├── api │ ├── feed │ │ ├── index.js │ │ └── route.js │ ├── users │ │ ├── index.js │ │ └── route.js │ ├── tags │ │ ├── index.js │ │ └── route.js │ ├── index.js │ ├── projects │ │ ├── index.js │ │ └── route.js │ ├── auth │ │ └── index.js │ └── posts │ │ ├── index.js │ │ └── route.js ├── config.template.json ├── models │ ├── tag.js │ ├── project.js │ ├── post.js │ └── user.js ├── auth │ ├── index.js │ ├── local │ │ ├── index.js │ │ └── passport.js │ └── service.js ├── package.json ├── views │ └── rss.jade ├── bin │ └── www └── app.js ├── README.md ├── .gitignore ├── .jshintrc └── .editorconfig /client/vendor/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/app/helpers/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/app/models/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/app/routes/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/tests/unit/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/app/components/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/app/controllers/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/app/styles/_projects.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/tests/integration/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/app/styles/blog-posts/_post-new.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /client/app/templates/auth.hbs: -------------------------------------------------------------------------------- 1 | {{outlet}} 2 | -------------------------------------------------------------------------------- /cache/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true 3 | } 4 | 5 | -------------------------------------------------------------------------------- /client/server/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true 3 | } 4 | -------------------------------------------------------------------------------- /server/.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | esnext: true 4 | } 5 | -------------------------------------------------------------------------------- /client/.watchmanconfig: -------------------------------------------------------------------------------- 1 | { 2 | "ignore_dirs": ["tmp", "dist"] 3 | } 4 | -------------------------------------------------------------------------------- /client/app/templates/projects.hbs: -------------------------------------------------------------------------------- 1 | {{outlet}} 2 | {{title "Projects"}} 3 | -------------------------------------------------------------------------------- /client/app/templates/stream.hbs: -------------------------------------------------------------------------------- 1 | {{lctv-frame}} 2 | {{outlet}} 3 | 4 | -------------------------------------------------------------------------------- /client/app/templates/blog-posts.hbs: -------------------------------------------------------------------------------- 1 | {{title "Blog"}} 2 | 3 | {{outlet}} 4 | -------------------------------------------------------------------------------- /client/app/styles/_helpers.scss: -------------------------------------------------------------------------------- 1 | .hidden { 2 | display: none !important; 3 | } 4 | -------------------------------------------------------------------------------- /client/public/robots.txt: -------------------------------------------------------------------------------- 1 | # http://www.robotstxt.org 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /client/.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "bower_components", 3 | "analytics": false 4 | } 5 | -------------------------------------------------------------------------------- /client/app/styles/components/_lctv-frame.scss: -------------------------------------------------------------------------------- 1 | #lctv-frame { 2 | margin-bottom: 40px; 3 | } 4 | -------------------------------------------------------------------------------- /client/app/resolver.js: -------------------------------------------------------------------------------- 1 | import Resolver from 'ember-resolver'; 2 | 3 | export default Resolver; 4 | -------------------------------------------------------------------------------- /client/app/routes/404.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | 3 | export default Ember.Route.extend({ 4 | }); 5 | -------------------------------------------------------------------------------- /client/app/templates/components/blog-post-body.hbs: -------------------------------------------------------------------------------- 1 |
No matter how long you are going to wait here, the page you requested will not come back.
5 |
6 |
--------------------------------------------------------------------------------
/client/app/controllers/application.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 |
3 | export default Ember.Controller.extend({
4 | session: Ember.inject.service('session'),
5 | user: Ember.inject.service('user'),
6 |
7 | init() {
8 | this._super(...arguments);
9 | }
10 | });
11 |
--------------------------------------------------------------------------------
/client/app/styles/components/_tags-list.scss:
--------------------------------------------------------------------------------
1 | .tags-list {
2 | list-style: none;
3 | margin: 0;
4 | padding: 0;
5 |
6 | li {
7 | display: inline-block;
8 | span {
9 | @include tag-style;
10 | }
11 | padding: 10px 0;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/server/models/tag.js:
--------------------------------------------------------------------------------
1 | var mongoose = require('mongoose');
2 | var Schema = mongoose.Schema;
3 |
4 | var TagSchema = new Schema({
5 | name: String,
6 | // posts: [{ type: Schema.Types.ObjectId, ref: 'Post' }],
7 | });
8 |
9 | module.exports = mongoose.model('Tag', TagSchema);
10 |
11 |
--------------------------------------------------------------------------------
/client/app/styles/auth/_login.scss:
--------------------------------------------------------------------------------
1 | .login-form {
2 | .error-message {
3 | padding: 12px 20px;
4 | color: white;
5 | background-color: $red;
6 |
7 | .message-title {
8 | margin-top: 0;
9 | font-weight: 700;
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/client/app/routes/projects.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 |
3 | export default Ember.Route.extend({
4 | actions: {
5 | save(project) {
6 | project.save().then(() => {
7 | this.transitionTo('projects.list');
8 | });
9 | }
10 | }
11 | });
12 |
--------------------------------------------------------------------------------
/client/app/serializers/post.js:
--------------------------------------------------------------------------------
1 | import DS from 'ember-data';
2 |
3 | export default DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
4 | primaryKey: '_id',
5 | attrs: {
6 | 'tags': {
7 | serialize: 'ids',
8 | deserialize: 'records'
9 | }
10 | }
11 | });
12 |
--------------------------------------------------------------------------------
/client/app/styles/blog-posts/_post-read.scss:
--------------------------------------------------------------------------------
1 | .post {
2 | p {
3 | margin: 0;
4 | padding: 0;
5 | }
6 |
7 | .hint {
8 | cursor: help;
9 | border-bottom: 1px dashed $grey;
10 | }
11 |
12 | .comments {
13 | margin-top: 20px;
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/client/testem.js:
--------------------------------------------------------------------------------
1 | /*jshint node:true*/
2 | module.exports = {
3 | "framework": "qunit",
4 | "test_page": "tests/index.html?hidepassed",
5 | "disable_watching": true,
6 | "launch_in_ci": [
7 | "PhantomJS"
8 | ],
9 | "launch_in_dev": [
10 | "PhantomJS",
11 | "Chrome"
12 | ]
13 | };
14 |
--------------------------------------------------------------------------------
/client/app/authenticators/oauth2.js:
--------------------------------------------------------------------------------
1 | import OAuth2PasswordGrant from 'ember-simple-auth/authenticators/oauth2-password-grant';
2 | import config from '../config/environment';
3 |
4 | export default OAuth2PasswordGrant.extend({
5 | serverTokenEndpoint: [config.API.host, config.API.namespace, 'auth/local'].join('/')
6 | });
7 |
--------------------------------------------------------------------------------
/client/app/templates/components/lctv-frame.hbs:
--------------------------------------------------------------------------------
1 | {{#if isLive}}
2 | Registration is closed. Sorry.
8 | {{#if errorMessage}} 9 | 11 | {{errorMessage}} 12 | 13 | {{/if}} 14 | 19 |test
'); 10 | 11 | this.render(hbs` 12 | {{#blog-post-body}} 13 | {{{html}}} 14 | {{/blog-post-body}} 15 | `); 16 | 17 | assert.equal(this.$().text().trim(), 'test'); 18 | assert.equal(this.$().find('.post-body').html().trim(), 'test
'); 19 | }); 20 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "predef": [ 3 | "document", 4 | "window", 5 | "-Promise" 6 | ], 7 | "browser": true, 8 | "boss": true, 9 | "curly": true, 10 | "debug": false, 11 | "devel": true, 12 | "eqeqeq": true, 13 | "evil": true, 14 | "forin": false, 15 | "immed": false, 16 | "laxbreak": false, 17 | "newcap": true, 18 | "noarg": true, 19 | "noempty": false, 20 | "nonew": false, 21 | "nomen": false, 22 | "onevar": false, 23 | "plusplus": false, 24 | "regexp": false, 25 | "undef": true, 26 | "sub": true, 27 | "strict": false, 28 | "white": false, 29 | "eqnull": true, 30 | "esnext": true, 31 | "unused": true 32 | } 33 | -------------------------------------------------------------------------------- /client/app/initializers/reset-navbar.js: -------------------------------------------------------------------------------- 1 | import Ember from 'ember'; 2 | 3 | var initialized = false; 4 | 5 | export function initialize() { 6 | if (initialized) { 7 | return; 8 | } 9 | 10 | Ember.Route.reopen({ 11 | actions: { 12 | didTransition() { 13 | Ember.$('.navbar').removeClass('show'); 14 | Ember.$('.nav-toggle').removeClass('active'); 15 | this._super(); 16 | return true; 17 | } 18 | } 19 | }); 20 | 21 | initialized = true; 22 | } 23 | 24 | export default { 25 | name: 'reset-navbar', 26 | initialize 27 | }; 28 | 29 | 30 | -------------------------------------------------------------------------------- /client/public/crossdomain.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 |6 | {{if item.isPublished "" "[ DRAFT ]"}} 7 | {{moment-from-now item.dateCreated interval=60000}} 8 |
9 |10 | {{#link-to "blog-posts.post-read" item}}{{item.title}}{{/link-to}} 11 |
12 |13 | {{item.description}} 14 |
15 | {{!-- 16 |17 | {{disqus-comment-count identifier=item.id}} 18 |
19 | --}} 20 | {{tags-list tags=item.tags}} 21 | {{!-- 22 | {{#if item.project}} 23 |24 | Related to project: {{item.project.name}} 25 |
26 | {{/if}} 27 | --}} 28 |15 | {{moment-from-now project.dateCreated interval=1000}} 16 |
17 |12 | {{if item.isPublished "" "[ DRAFT ]"}} 13 | {{moment-from-now item.dateCreated interval=60000}} 14 |
15 |19 | {{item.description}} 20 |
21 | {{tags-list tags=item.tags}} 22 | {{!-- 23 | {{#if item.project}} 24 |25 | Related to project: {{item.project.name}} 26 |
27 | {{/if}} 28 | --}} 29 |4 | Hello, my name is {{model.name}}. I love my wife, JavaScript, and Vim. 5 |
6 |7 | I'm somewhat social: 8 |
24 | I do: 25 |
21 | {{if model.isPublished "" "[ DRAFT ]"}} 22 | {{moment-format model.dateCreated "DD/MM/YY HH:mm"}} 23 |
24 |\
24 | console.log("hehehe");\
25 | '
26 | }
27 | ]
28 | };
29 |
30 | /*jshint node:true*/
31 | module.exports = function(app) {
32 | var express = require('express');
33 | var postsRouter = express.Router();
34 |
35 | postsRouter.get('/', function(req, res) {
36 | res.send(data);
37 | });
38 |
39 | postsRouter.post('/', function(req, res) {
40 | var post = req.body.post;
41 | post.id = data.posts.length + 1;
42 | res.status(201).json({
43 | 'posts': post
44 | });
45 | });
46 |
47 | postsRouter.get('/:id', function(req, res) {
48 | var postData = data.posts.filter(function(post) {
49 | return post.id === req.params.id;
50 | })[0]
51 | res.send({
52 | 'posts': postData
53 | });
54 | });
55 |
56 | postsRouter.put('/:id', function(req, res) {
57 | res.send({
58 | 'posts': {
59 | id: req.params.id
60 | }
61 | });
62 | });
63 |
64 | postsRouter.delete('/:id', function(req, res) {
65 | res.status(204).end();
66 | });
67 |
68 | // The POST and PUT call will not contain a request body
69 | // because the body-parser is not included by default.
70 | // To use req.body, run:
71 |
72 | // npm install --save-dev body-parser
73 |
74 | // After installing, you need to `use` the body-parser for
75 | // this mock uncommenting the following line:
76 | //
77 | var bodyParser = require('body-parser');
78 | app.use(bodyParser.urlencoded({ extended: false }));
79 | app.use(bodyParser.json());
80 | app.use('/api/posts', postsRouter);
81 | };
82 |
--------------------------------------------------------------------------------
/client/app/components/autocomplete-input.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 |
3 | export default Ember.Component.extend({
4 | store: Ember.inject.service(),
5 |
6 | foundItems: null,
7 | newItem: null,
8 |
9 | addItem(value) {
10 | if (typeof value === 'string') {
11 | value = this.get('store').createRecord('tag', {
12 | name: value
13 | });
14 | }
15 | if (this.get('items')) {
16 | this.get('items').addObject(value);
17 | } else if (this.get('item')) {
18 | this.set('item', value);
19 | }
20 | this.set('foundItems', []);
21 | this.set('newItem', null);
22 | },
23 |
24 | removeItem(value) {
25 | if (this.get('items')) {
26 | this.get('items').removeObject(value);
27 | } else if (this.get('item')) {
28 | this.set('item', undefined);
29 | }
30 | },
31 |
32 | findItem(value) {
33 | let { store, model, key } = this.getProperties('store', 'model', 'key');
34 |
35 | let query = {};
36 | query[key] = { '$regex': value };
37 |
38 | store.query(model, query).then((items) => {
39 | this.set('foundItems', items);
40 | });
41 | },
42 |
43 | actions: {
44 | remove(value) {
45 | this.removeItem(value);
46 | },
47 |
48 | add(value) {
49 | this.addItem(value);
50 | },
51 |
52 | keyUp(value, event) {
53 | let key = event.keyCode;
54 | switch (key) {
55 | // This is comma
56 | case 188:
57 | value = value.slice(0, -1);
58 | this.addItem(value);
59 | return;
60 |
61 | // Enter key
62 | case 13:
63 | this.addItem(value);
64 | return;
65 |
66 | default:
67 | if (value) {
68 | this.findItem(value);
69 | } else {
70 | // No need of querying and displaying old values
71 | // if value is empty
72 | this.set('foundItems', []);
73 | }
74 | return;
75 |
76 | }
77 | }
78 | }
79 | });
80 |
--------------------------------------------------------------------------------
/server/models/post.js:
--------------------------------------------------------------------------------
1 | var mongoose = require('mongoose');
2 | var marked = require('marked');
3 | var Tag = require('./tag');
4 | var Schema = mongoose.Schema;
5 |
6 | var PostSchema = new Schema({
7 | title: String,
8 | body: String,
9 | markdown: String,
10 | description: String,
11 | slug: String,
12 | dateCreated: Date,
13 | isPublished: Boolean,
14 | tags: [{ type: Schema.Types.ObjectId, ref: 'Tag' }],
15 | project: { type: Schema.Types.ObjectId, ref: 'Project' }
16 | });
17 |
18 | /*
19 | * Creates a slug
20 | */
21 | function slugify(text) {
22 |
23 | return text
24 | .toString().toLowerCase()
25 | .replace(/\s+/g, '-') // Replace spaces with -
26 | .replace(/[^\w\-]+/g, '') // Remove all non-word chars
27 | .replace(/\-\-+/g, '-') // Replace multiple - with single -
28 | .replace(/^-+/, '') // Trim - from start of text
29 | .replace(/-+$/, ''); // Trim - from end of text
30 | }
31 |
32 | /*
33 | * Transliteration
34 | */
35 | function translit(text) {
36 | var letters = {
37 | 'а': 'a',
38 | 'б': 'b',
39 | 'в': 'v',
40 | 'г': 'g',
41 | 'д': 'd',
42 | 'е': 'e',
43 | 'ё': 'e',
44 | 'ж': 'zh',
45 | 'з': 'z',
46 | 'и': 'i',
47 | 'й': 'j',
48 | 'к': 'k',
49 | 'л': 'l',
50 | 'м': 'm',
51 | 'н': 'n',
52 | 'о': 'o',
53 | 'п': 'p',
54 | 'р': 'r',
55 | 'с': 's',
56 | 'т': 't',
57 | 'у': 'u',
58 | 'ф': 'f',
59 | 'х': 'h',
60 | 'ц': 'c',
61 | 'ч': 'ch',
62 | 'ш': 'sh',
63 | 'щ': 'sh',
64 | 'ъ': '\'',
65 | 'ы': 'y',
66 | 'ь': '\'',
67 | 'э': 'e',
68 | 'ю': 'yu',
69 | 'я': 'ya'
70 | };
71 |
72 | var string = '';
73 |
74 | Array.prototype.forEach.call(text.toLowerCase(), function(char) {
75 | if (letters[char]) {
76 | string += letters[char];
77 | } else {
78 | string += char;
79 | }
80 | });
81 |
82 | return string;
83 | }
84 |
85 | PostSchema.pre('save', function(next) {
86 | if (!this.title || !this.markdown) {
87 | throw 'No valid post object is specified';
88 | }
89 | this.slug = translit(this.title);
90 | this.slug = slugify(this.slug);
91 | this.body = marked(this.markdown);
92 | next();
93 | });
94 |
95 | module.exports = mongoose.model('Post', PostSchema);
96 |
--------------------------------------------------------------------------------
/client/app/templates/components/post-edit-form.hbs:
--------------------------------------------------------------------------------
1 | 30 | {{moment-from-now post.dateCreated interval=60000}} 31 |
32 |16 | Created {{moment-from-now project.dateCreated}} 17 |
18 | {{#if project.dateUpdated}} 19 |20 | Updated {{moment-from-now project.dateUpdated}} 21 |
22 | {{/if}} 23 |33 | {{project.description}} 34 |
35 |36 | {{#if project.isOwner}} 37 | [ owner ] 38 | {{else}} 39 | [ collaborator ] 40 | {{/if}} 41 |
42 |50 | [ draft ] 51 | Publish 52 |
53 |54 | Created {{moment-from-now project.dateCreated}} 55 |
56 |57 | Updated {{moment-from-now project.dateUpdated}} 58 |
59 |63 | {{project.description}} 64 |
65 |66 | {{#if project.isOwner}} 67 | [ owner ] 68 | {{else}} 69 | [ collaborator ] 70 | {{/if}} 71 |
72 |
Comments
41 | {{disqus-comments identifier=model.id title=model.title}} 42 |