Resolve #43 - Implement markdown, remove disfunctional newlines.coffee

This commit is contained in:
Zeusking19 2015-12-27 15:59:38 +00:00
parent a9ce4aabce
commit 605c8b7f99
11 changed files with 1660 additions and 29 deletions

View file

@ -88,6 +88,7 @@ class Assets
return [ return [
"scripts/base/jquery-2.0.2.js", "scripts/base/jquery-2.0.2.js",
"scripts/base/angular.js", "scripts/base/angular.js",
"scripts/base/marked.js",
"scripts/base/*.{coffee,js}", "scripts/base/*.{coffee,js}",
"scripts/shared/*.{coffee,js}", "scripts/shared/*.{coffee,js}",
"scripts/app/*.{coffee,js}", "scripts/app/*.{coffee,js}",

View file

@ -52,7 +52,7 @@
<div class="left"> <div class="left">
<div class="description" bo-show="album.description.length"> <div class="description" bo-show="album.description.length">
<h2>Description</h2> <h2>Description</h2>
<p bo-html="album.description | linky:'_blank':{rel: 'nofollow'} | newlines"></p> <p marked="album.description"></p>
</div> </div>
<h2>Tracks</h2> <h2>Tracks</h2>

View file

@ -3,7 +3,7 @@
<div bo-show="artist.bio.trim().length"> <div bo-show="artist.bio.trim().length">
<h2>Bio</h2> <h2>Bio</h2>
<div class="description"> <div class="description">
<p bo-html="artist.bio | linky:'_blank':{rel: 'nofollow'} | newlines"></p> <p marked="artist.bio"></p>
</div> </div>
</div> </div>

View file

@ -13,7 +13,7 @@
<img pfm-src-loader="comment.user.avatars.thumbnail" pfm-src-size="thumbnail" /> <img pfm-src-loader="comment.user.avatars.thumbnail" pfm-src-size="thumbnail" />
<div class="content"> <div class="content">
<a bo-href="comment.user.url" bo-text="comment.user.name"></a> <a bo-href="comment.user.url" bo-text="comment.user.name"></a>
<span bo-html="comment.content | linky:'_blank':{rel: 'nofollow'}"></span> <span marked="comment.content"></span>
<div class="meta" bo-text="comment.created_at.date | momentFromNow"> <div class="meta" bo-text="comment.created_at.date | momentFromNow">
</div> </div>
</div> </div>

View file

@ -51,7 +51,7 @@
<div class="left"> <div class="left">
<div class="description" bo-show="playlist.description.length"> <div class="description" bo-show="playlist.description.length">
<h2>Description</h2> <h2>Description</h2>
<p bo-html="playlist.description | linky:'_blank':{rel: 'nofollow'} | newlines"></p> <p marked="playlist.description"></p>
</div> </div>
<h2>Tracks</h2> <h2>Tracks</h2>

View file

@ -71,7 +71,7 @@
<div class="left"> <div class="left">
<div class="description" bo-show="track.description.length"> <div class="description" bo-show="track.description.length">
<h2>Description</h2> <h2>Description</h2>
<p bo-html="track.description | linky:'_blank':{rel: 'nofollow'} | newlines"></p> <p marked="track.description"></p>
</div> </div>
<div bo-show="track.is_vocal && track.lyrics.length" class="lyrics-panel"> <div bo-show="track.is_vocal && track.lyrics.length" class="lyrics-panel">
@ -80,7 +80,7 @@
<div class="reveal"> <div class="reveal">
<a href="#">Click to reveal full lyrics...</a> <a href="#">Click to reveal full lyrics...</a>
</div> </div>
<p class="content" bo-html="track.lyrics | noHTML | newlines"></p> <p class="content" bo-html="track.lyrics | noHTML | nl2br"></p>
</div> </div>
</div> </div>

View file

@ -16,7 +16,7 @@
window.pfm.preloaders = {} window.pfm.preloaders = {}
module = angular.module 'ponyfm', ['ui.bootstrap', 'ui.state', 'ui.date', 'ui.sortable', 'pasvaz.bindonce', 'angularytics', 'ngSanitize'] module = angular.module 'ponyfm', ['ui.bootstrap', 'ui.state', 'ui.date', 'ui.sortable', 'pasvaz.bindonce', 'angularytics', 'ngSanitize', 'hc.marked']
if window.pfm.environment == 'production' if window.pfm.environment == 'production'
module.run [ module.run [
@ -33,8 +33,8 @@ module.run [
] ]
module.config [ module.config [
'$locationProvider', '$stateProvider', '$dialogProvider', 'AngularyticsProvider', '$httpProvider', '$sceDelegateProvider' '$locationProvider', '$stateProvider', '$dialogProvider', 'AngularyticsProvider', '$httpProvider', '$sceDelegateProvider', 'markedProvider'
(location, state, $dialogProvider, analytics, $httpProvider, $sceDelegateProvider) -> (location, state, $dialogProvider, analytics, $httpProvider, $sceDelegateProvider, markedProvider) ->
if window.pfm.environment == 'local' if window.pfm.environment == 'local'
$httpProvider.interceptors.push [ $httpProvider.interceptors.push [
@ -54,6 +54,16 @@ module.config [
if window.pfm.environment == 'production' if window.pfm.environment == 'production'
analytics.setEventHandlers ['Google'] analytics.setEventHandlers ['Google']
markedProvider.setOptions
gfm: true
tables: true
sanitize: true
smartLists: true
smartypants: true
markedProvider.setRenderer link: (href, title, text) ->
'<a href="' + href + '"' + (if title then ' title="' + title + '"' else '') + ' target="_blank">' + text + '</a>'
# Errors # Errors
state.state 'errors-404', state.state 'errors-404',
url: '/errors/not-found' url: '/errors/not-found'

View file

@ -1,20 +0,0 @@
# Pony.fm - A community for pony fan music.
# Copyright (C) 2015 Peter Deltchev
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
angular.module('ponyfm').filter 'newlines', () ->
(input) ->
return '' if !input
input.replace(/\n/g, '<br/>')

View file

@ -0,0 +1,9 @@
angular.module('ponyfm').filter 'nl2br', [
'$sanitize'
($sanitize) ->
tag = if /xhtml/i.test(document.doctype) then '<br />' else '<br>'
(msg) ->
# ngSanitize's linky filter changes \r and \n to &#10; and &#13; respectively
msg = (msg + '').replace(/(\r\n|\n\r|\r|\n|&#10;&#13;|&#13;&#10;|&#10;|&#13;)/g, tag + '$1')
$sanitize msg
]

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,346 @@
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.angularMarked = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
/*
* This is a modified version of angular-marked.js for Pony.fm to provide compatibility with Angular 1.2.0.
*
* angular-marked
* (c) 2014 J. Harshbarger
* Licensed MIT
*/
/* jshint undef: true, unused: true */
/* global angular, marked */
'use strict';
/**
* @ngdoc overview
* @name index
*
* @description
* AngularJS Markdown using [marked](https://github.com/chjj/marked).
*
* ## Why?
*
* I wanted to use [marked](https://github.com/chjj/marked) instead of [showdown](https://github.com/coreyti/showdown) as used in [angular-markdown-directive](https://github.com/btford/angular-markdown-directive) as well as expose the option to globally set defaults.
*
* ## How?
*
* - {@link hc.marked.directive:marked As a directive}
* - {@link hc.marked.service:marked As a service}
* - {@link hc.marked.service:markedProvider Set default options}
*
* @example
Convert markdown to html at run time. For example:
<example module="app">
<file name="example.html">
<form ng-controller="MainController">
Markdown:<br />
<textarea ng-model="my_markdown" cols="60" rows="5" class="span8"></textarea><br />
Output:<br />
<div marked="my_markdown" />
</form>
</file>
<file name="example.js">
function MainController($scope) {
$scope.my_markdown = "*This* **is** [markdown](https://daringfireball.net/projects/markdown/)";
}
angular.module('app', ['hc.marked']).controller('MainController', MainController);
</file>
</example>
*
*/
/**
* @ngdoc overview
* @name hc.marked
* @description # angular-marked (core module)
# Installation
First include angular-marked.js in your HTML:
```js
<script src="angular-marked.js">
```
Then load the module in your application by adding it as a dependency:
```js
angular.module('yourApp', ['hc.marked']);
```
With that you're ready to get started!
*/
module.exports = 'hc.marked';
angular.module('hc.marked', [])
/**
* @ngdoc service
* @name hc.marked.service:marked
* @requires $window
* @description
* A reference to the [marked](https://github.com/chjj/marked) parser.
*
* @example
<example module="app">
<file name="example.html">
<div ng-controller="MainController">
html: {{html}}
</div>
</file>
<file name="example.js">
function MainController($scope, marked) {
$scope.html = marked('#TEST');
}
angular.module('app', ['hc.marked']).controller('MainController', MainController);
</file>
</example>
**/
/**
* @ngdoc service
* @name hc.marked.service:markedProvider
* @description
* Use `markedProvider` to change the default behavior of the {@link hc.marked.service:marked marked} service.
*
* @example
## Example using [google-code-prettify syntax highlighter](https://code.google.com/p/google-code-prettify/) (must include google-code-prettify.js script). Also works with [highlight.js Javascript syntax highlighter](http://highlightjs.org/).
<example module="myAppA">
<file name="exampleA.js">
angular.module('myAppA', ['hc.marked'])
.config(['markedProvider', function(markedProvider) {
markedProvider.setOptions({
gfm: true,
tables: true,
highlight: function (code) {
return prettyPrintOne(code);
}
});
}]);
</file>
<file name="exampleA.html">
<marked>
```js
angular.module('myAppA', ['hc.marked'])
.config(['markedProvider', function(markedProvider) {
markedProvider.setOptions({
gfm: true,
tables: true,
highlight: function (code) {
return prettyPrintOne(code);
}
});
}]);
```
</marked>
</file>
</example>
## Example overriding the way custom markdown links are displayed
<example module="myAppB">
<file name="exampleB.js">
angular.module('myAppB', ['hc.marked'])
.config(['markedProvider', function(markedProvider) {
markedProvider.setRenderer({
link: function(href, title, text) {
return "<a href='" + href + "'" + (title ? " title='" + title + "'" : '') + " target='_blank'>" + text + "</a>";
}
});
}]);
</file>
<file name="exampleB.html">
<marked>
This is [an example](http://example.com/ "Title") inline link.
[This link](http://example.net/) has no title attribute.
</marked>
</file>
</example>
**/
.provider('marked', function () {
var self = this;
/**
* @ngdoc method
* @name markedProvider#setRenderer
* @methodOf hc.marked.service:markedProvider
*
* @param {object} opts Default renderer options for [marked](https://github.com/chjj/marked#overriding-renderer-methods).
*/
self.setRenderer = function (opts) {
this.renderer = opts;
};
/**
* @ngdoc method
* @name markedProvider#setOptions
* @methodOf hc.marked.service:markedProvider
*
* @param {object} opts Default options for [marked](https://github.com/chjj/marked#options-1).
*/
self.setOptions = function (opts) { // Store options for later
this.defaults = opts;
};
self.$get = ['$log', '$window', function ($log, $window) {
var m;
try {
m = require('marked');
} catch (e) {
m = $window.marked || marked;
}
if (angular.isUndefined(m)) {
$log.error('angular-marked Error: marked not loaded. See installation instructions.');
return;
}
// override rendered markdown html
// with custom definitions if defined
if (self.renderer) {
var r = new m.Renderer();
var o = Object.keys(self.renderer);
var l = o.length;
while (l--) {
r[o[l]] = self.renderer[o[l]];
}
// add the new renderer to the options if need be
self.defaults = self.defaults || {};
self.defaults.renderer = r;
}
m.setOptions(self.defaults);
return m;
}];
})
// TODO: filter and tests */
// app.filter('marked', ['marked', function(marked) {
// return marked;
// }]);
/**
* @ngdoc directive
* @name hc.marked.directive:marked
* @restrict AE
* @element any
*
* @description
* Compiles source test into HTML.
*
* @param {expression=} marked The source text to be compiled. If blank uses content as the source.
* @param {expression=} opts Hash of options that override defaults.
* @param {string=} src Expression evaluating to URL. If the source is a string constant,
* make sure you wrap it in **single** quotes, e.g. `src="'myPartialTemplate.html'"`.
*
* @example
## A simple block of text
<example module="hc.marked">
<file name="exampleA.html">
* <marked>
* ### Markdown directive
*
* *It works!*
*
* *This* **is** [markdown](https://daringfireball.net/projects/markdown/) in the view.
* </marked>
</file>
</example>
## Bind to a scope variable
<example module="app">
<file name="exampleB.html">
<form ng-controller="MainController">
Markdown:<br />
<textarea ng-model="my_markdown" class="span8" cols="60" rows="5"></textarea><br />
Output:<br />
<blockquote marked="my_markdown"></blockquote>
</form>
</file>
<file name="exampleB.js">
* function MainController($scope) {
* $scope.my_markdown = '*This* **is** [markdown](https://daringfireball.net/projects/markdown/)';
* $scope.my_markdown += ' in a scope variable';
* }
* angular.module('app', ['hc.marked']).controller('MainController', MainController);
</file>
</example>
## Include a markdown file:
<example module="hc.marked">
<file name="exampleC.html">
<div marked src="'include.html'" />
</file>
* <file name="include.html">
* *This* **is** [markdown](https://daringfireball.net/projects/markdown/) in a include file.
* </file>
</example>
*/
.directive('marked', ['marked', function (marked) {
return {
restrict: 'AE',
replace: true,
scope: {
opts: '=',
marked: '='
},
link: function (scope, element, attrs) {
set(scope.marked || element.text() || '');
if (attrs.marked) {
scope.$watch('marked', set);
}
function unindent (text) {
if (!text) return text;
var lines = text
.replace(/\t/g, ' ')
.split(/\r?\n/);
var min = null;
var len = lines.length;
var l, line;
for (var i = 0; i < len; i++) {
line = lines[i];
l = line.match(/^(\s*)/)[0].length;
if (l === line.length) { continue; }
min = (l < min || min === null) ? l : min;
}
if (min !== null && min > 0) {
for (i = 0; i < len; i++) {
lines[i] = lines[i].substr(min);
}
}
return lines.join('\n');
}
function set (text) {
text = unindent(text || '');
element.html(marked(text, scope.opts || null));
}
}
};
}]);
},{"marked":"marked"}]},{},[1])(1)
});