Render descriptions and comments as Markdown
When displaying comments and descriptions for projects or stories, render the content as Markdown before displaying it. This is a simple way to support rich text descriptions and comments, and there is no special editor as yet. Any code in the supplied Markdown (indented by 4 spaces) will have its syntax highlighted. The `highlightjs` module is used for syntax highlighting and the `marked` module is used for parsing the Markdown. Also, stop eslint from raising an error when it thinks something is undefined, and raise a warning instead. This is because the use of `hljs` and `marked` was confusing the linter into thinking they weren't defined. Change-Id: I7896fd686a39e27f8068ee6db6747b2b5ab0ccfc
This commit is contained in:
parent
ec0f5651cd
commit
cdf7944065
@ -49,6 +49,7 @@
|
|||||||
"no-trailing-spaces": 2,
|
"no-trailing-spaces": 2,
|
||||||
"camelcase": 0,
|
"camelcase": 0,
|
||||||
"no-extra-boolean-cast": 0,
|
"no-extra-boolean-cast": 0,
|
||||||
|
"no-undef": 1,
|
||||||
|
|
||||||
// Stylistic
|
// Stylistic
|
||||||
"indent": [2, 4],
|
"indent": [2, 4],
|
||||||
|
@ -149,7 +149,8 @@ module.exports = function (grunt) {
|
|||||||
dir.theme + '/custom/',
|
dir.theme + '/custom/',
|
||||||
dir.theme + '/storyboard/',
|
dir.theme + '/storyboard/',
|
||||||
dir.bower + '/bootstrap/less/',
|
dir.bower + '/bootstrap/less/',
|
||||||
dir.bower + '/font-awesome/less/'
|
dir.bower + '/font-awesome/less/',
|
||||||
|
dir.bower + '/highlightjs/styles/'
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
cleancss: true,
|
cleancss: true,
|
||||||
|
@ -13,7 +13,9 @@
|
|||||||
"angular-elastic": "2.4.2",
|
"angular-elastic": "2.4.2",
|
||||||
"angular-moment": "0.9.0",
|
"angular-moment": "0.9.0",
|
||||||
"angular-cache": "3.2.5",
|
"angular-cache": "3.2.5",
|
||||||
"angularjs-viewhead": "0.0.1"
|
"angularjs-viewhead": "0.0.1",
|
||||||
|
"marked": "0.3.4",
|
||||||
|
"highlightjs": "8.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"angular-mocks": "1.3.13",
|
"angular-mocks": "1.3.13",
|
||||||
|
@ -46,9 +46,9 @@
|
|||||||
</small>
|
</small>
|
||||||
</h1>
|
</h1>
|
||||||
<p>
|
<p>
|
||||||
<span ng-show="project.description"
|
<insert-markdown ng-if="project.description && !isLoading"
|
||||||
class="honor-carriage-return">{{project.description}}
|
content="project.description">
|
||||||
</span>
|
</insert-markdown>
|
||||||
<em ng-hide="project.description" class="text-muted">
|
<em ng-hide="project.description" class="text-muted">
|
||||||
No description provided
|
No description provided
|
||||||
</em>
|
</em>
|
||||||
|
35
src/app/services/directive/markdown.js
Normal file
35
src/app/services/directive/markdown.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015 Codethink Limited.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the 'License'); you may
|
||||||
|
* not use this file except in compliance with the License. You may obtain
|
||||||
|
* a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an 'AS IS' BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service for rendering text as markdown.
|
||||||
|
*/
|
||||||
|
angular.module('sb.services')
|
||||||
|
.directive('insertMarkdown', function($sanitize) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
return {
|
||||||
|
restrict: 'E',
|
||||||
|
scope: {
|
||||||
|
content: '='
|
||||||
|
},
|
||||||
|
link: function(scope, elem) {
|
||||||
|
scope.$watch('content', function(newVal) {
|
||||||
|
elem.html('<div>' + $sanitize(marked(newVal)) + '</div>');
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
@ -4,9 +4,9 @@
|
|||||||
<span time-moment eventdate="event.created_at" class="pull-right"></span>
|
<span time-moment eventdate="event.created_at" class="pull-right"></span>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p ng-show="event.comment.content"
|
<insert-markdown ng-show="event.comment.content"
|
||||||
class="honor-carriage-return">{{event.comment.content}}
|
content="event.comment.content">
|
||||||
</p>
|
</insert-markdown>
|
||||||
|
|
||||||
<p><em ng-hide="event.comment.content"
|
<p><em ng-hide="event.comment.content"
|
||||||
class="text-muted">
|
class="text-muted">
|
||||||
|
@ -38,7 +38,6 @@
|
|||||||
<!-- Template for the header and description -->
|
<!-- Template for the header and description -->
|
||||||
<script type="text/ng-template" id="/inline/story_detail.html">
|
<script type="text/ng-template" id="/inline/story_detail.html">
|
||||||
<h1>
|
<h1>
|
||||||
|
|
||||||
<span ng-show="story.title" view-title>
|
<span ng-show="story.title" view-title>
|
||||||
{{story.title}}
|
{{story.title}}
|
||||||
</span>
|
</span>
|
||||||
@ -52,11 +51,6 @@
|
|||||||
</a>
|
</a>
|
||||||
<subscribe resource="story"
|
<subscribe resource="story"
|
||||||
resource-id="story.id"></subscribe>
|
resource-id="story.id"></subscribe>
|
||||||
<button type="button"
|
|
||||||
class="btn btn-link"
|
|
||||||
ng-click="remove()" permission="is_superuser">
|
|
||||||
Remove this story
|
|
||||||
</button>
|
|
||||||
</small>
|
</small>
|
||||||
</h1>
|
</h1>
|
||||||
<p><strong>Author:</strong>
|
<p><strong>Author:</strong>
|
||||||
@ -78,9 +72,9 @@
|
|||||||
</em>
|
</em>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<span ng-show="story.description"
|
<insert-markdown ng-show="story.description"
|
||||||
class="honor-carriage-return">{{story.description}}
|
content="story.description">
|
||||||
</span>
|
</insert-markdown>
|
||||||
<em ng-hide="story.description" class="text-muted">
|
<em ng-hide="story.description" class="text-muted">
|
||||||
No description provided
|
No description provided
|
||||||
</em>
|
</em>
|
||||||
|
@ -24,8 +24,9 @@
|
|||||||
</a>
|
</a>
|
||||||
</strong>
|
</strong>
|
||||||
<br/>
|
<br/>
|
||||||
<small class="text-muted honor-carriage-return"
|
<small class="text-muted"
|
||||||
ng-show="expandRow">{{story.description}}
|
ng-show="expandRow">
|
||||||
|
<insert-markdown content="story.description"></insert-markdown>
|
||||||
</small>
|
</small>
|
||||||
</p>
|
</p>
|
||||||
</td>
|
</td>
|
||||||
|
@ -27,7 +27,7 @@ angular.module('storyboard',
|
|||||||
'sb.auth', 'sb.story', 'sb.profile', 'sb.notification', 'sb.search',
|
'sb.auth', 'sb.story', 'sb.profile', 'sb.notification', 'sb.search',
|
||||||
'sb.admin', 'sb.subscription', 'sb.project_group', 'ui.router',
|
'sb.admin', 'sb.subscription', 'sb.project_group', 'ui.router',
|
||||||
'ui.bootstrap', 'monospaced.elastic', 'angularMoment',
|
'ui.bootstrap', 'monospaced.elastic', 'angularMoment',
|
||||||
'angular-data.DSCacheFactory', 'viewhead'])
|
'angular-data.DSCacheFactory', 'viewhead', 'ngSanitize'])
|
||||||
.constant('angularMomentConfig', {
|
.constant('angularMomentConfig', {
|
||||||
preprocess: 'utc',
|
preprocess: 'utc',
|
||||||
timezone: 'UTC'
|
timezone: 'UTC'
|
||||||
@ -62,6 +62,13 @@ angular.module('storyboard',
|
|||||||
preferences: PreferenceResolver.resolvePreferences
|
preferences: PreferenceResolver.resolvePreferences
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Set up syntax highlighting for the markdown parser
|
||||||
|
marked.setOptions({
|
||||||
|
highlight: function (code) {
|
||||||
|
return hljs.highlightAuto(code).value;
|
||||||
|
}
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.run(function ($log, $rootScope, $document) {
|
.run(function ($log, $rootScope, $document) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
@ -39,6 +39,8 @@
|
|||||||
<script src="moment/moment.js"></script>
|
<script src="moment/moment.js"></script>
|
||||||
<script src="angular-moment/angular-moment.js"></script>
|
<script src="angular-moment/angular-moment.js"></script>
|
||||||
<script src="angularjs-viewhead/angularjs-viewhead.js"></script>
|
<script src="angularjs-viewhead/angularjs-viewhead.js"></script>
|
||||||
|
<script src="marked/marked.min.js"></script>
|
||||||
|
<script src="highlightjs/highlight.pack.js"></script>
|
||||||
<!-- endbuild -->
|
<!-- endbuild -->
|
||||||
|
|
||||||
<link rel="stylesheet" href="styles/main.css">
|
<link rel="stylesheet" href="styles/main.css">
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
padding: @table-condensed-cell-padding;
|
padding: @table-condensed-cell-padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
> p {
|
> insert-markdown > div, > p {
|
||||||
padding: @table-cell-padding;
|
padding: @table-cell-padding;
|
||||||
padding-bottom: 0px;
|
padding-bottom: 0px;
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
@import './bootstrap.less';
|
@import './bootstrap.less';
|
||||||
@import './base/bootstrap/navbar.less';
|
@import './base/bootstrap/navbar.less';
|
||||||
@import './font-awesome.less';
|
@import './font-awesome.less';
|
||||||
|
@import (less) './default.css';
|
||||||
|
|
||||||
// Theme
|
// Theme
|
||||||
@import './theme.less';
|
@import './theme.less';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user