mirror of
https://github.com/Poniverse/Pony.fm.git
synced 2024-11-25 22:47:59 +01:00
Resolve #43 - Implement markdown, remove disfunctional newlines.coffee
This commit is contained in:
parent
a9ce4aabce
commit
605c8b7f99
11 changed files with 1660 additions and 29 deletions
|
@ -88,6 +88,7 @@ class Assets
|
|||
return [
|
||||
"scripts/base/jquery-2.0.2.js",
|
||||
"scripts/base/angular.js",
|
||||
"scripts/base/marked.js",
|
||||
"scripts/base/*.{coffee,js}",
|
||||
"scripts/shared/*.{coffee,js}",
|
||||
"scripts/app/*.{coffee,js}",
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
<div class="left">
|
||||
<div class="description" bo-show="album.description.length">
|
||||
<h2>Description</h2>
|
||||
<p bo-html="album.description | linky:'_blank':{rel: 'nofollow'} | newlines"></p>
|
||||
<p marked="album.description"></p>
|
||||
</div>
|
||||
|
||||
<h2>Tracks</h2>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<div bo-show="artist.bio.trim().length">
|
||||
<h2>Bio</h2>
|
||||
<div class="description">
|
||||
<p bo-html="artist.bio | linky:'_blank':{rel: 'nofollow'} | newlines"></p>
|
||||
<p marked="artist.bio"></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<img pfm-src-loader="comment.user.avatars.thumbnail" pfm-src-size="thumbnail" />
|
||||
<div class="content">
|
||||
<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>
|
||||
</div>
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
<div class="left">
|
||||
<div class="description" bo-show="playlist.description.length">
|
||||
<h2>Description</h2>
|
||||
<p bo-html="playlist.description | linky:'_blank':{rel: 'nofollow'} | newlines"></p>
|
||||
<p marked="playlist.description"></p>
|
||||
</div>
|
||||
|
||||
<h2>Tracks</h2>
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
<div class="left">
|
||||
<div class="description" bo-show="track.description.length">
|
||||
<h2>Description</h2>
|
||||
<p bo-html="track.description | linky:'_blank':{rel: 'nofollow'} | newlines"></p>
|
||||
<p marked="track.description"></p>
|
||||
</div>
|
||||
|
||||
<div bo-show="track.is_vocal && track.lyrics.length" class="lyrics-panel">
|
||||
|
@ -80,7 +80,7 @@
|
|||
<div class="reveal">
|
||||
<a href="#">Click to reveal full lyrics...</a>
|
||||
</div>
|
||||
<p class="content" bo-html="track.lyrics | noHTML | newlines"></p>
|
||||
<p class="content" bo-html="track.lyrics | noHTML | nl2br"></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
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'
|
||||
module.run [
|
||||
|
@ -33,8 +33,8 @@ module.run [
|
|||
]
|
||||
|
||||
module.config [
|
||||
'$locationProvider', '$stateProvider', '$dialogProvider', 'AngularyticsProvider', '$httpProvider', '$sceDelegateProvider'
|
||||
(location, state, $dialogProvider, analytics, $httpProvider, $sceDelegateProvider) ->
|
||||
'$locationProvider', '$stateProvider', '$dialogProvider', 'AngularyticsProvider', '$httpProvider', '$sceDelegateProvider', 'markedProvider'
|
||||
(location, state, $dialogProvider, analytics, $httpProvider, $sceDelegateProvider, markedProvider) ->
|
||||
|
||||
if window.pfm.environment == 'local'
|
||||
$httpProvider.interceptors.push [
|
||||
|
@ -54,6 +54,16 @@ module.config [
|
|||
if window.pfm.environment == 'production'
|
||||
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
|
||||
state.state 'errors-404',
|
||||
url: '/errors/not-found'
|
||||
|
|
|
@ -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/>')
|
9
resources/assets/scripts/app/filters/nl2br.coffee
Normal file
9
resources/assets/scripts/app/filters/nl2br.coffee
Normal 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 and respectively
|
||||
msg = (msg + '').replace(/(\r\n|\n\r|\r|\n| | | | )/g, tag + '$1')
|
||||
$sanitize msg
|
||||
]
|
1285
resources/assets/scripts/base/marked.js
Normal file
1285
resources/assets/scripts/base/marked.js
Normal file
File diff suppressed because it is too large
Load diff
346
resources/assets/scripts/shared/pfm-angular-marked.js
Normal file
346
resources/assets/scripts/shared/pfm-angular-marked.js
Normal 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)
|
||||
});
|
Loading…
Reference in a new issue