Fix usericons (#1408)
* Fix and refactor user icons, add Basic tests * Remove identicon_canvas, use identicon.js * Use octicon by default
This commit is contained in:
+3
-3
@@ -149,9 +149,9 @@ MSG
|
|||||||
opts.on("--no-display-metadata", "Do not render metadata tables in pages.") do
|
opts.on("--no-display-metadata", "Do not render metadata tables in pages.") do
|
||||||
wiki_options[:display_metadata] = false
|
wiki_options[:display_metadata] = false
|
||||||
end
|
end
|
||||||
opts.on("--user-icons [MODE]", [:gravatar, :identicon, :none], "Use specific user-icons for history view.",
|
opts.on("--user-icons [MODE]", [:gravatar, :identicon], "Use specific user-icons for history view.",
|
||||||
"Can be set to 'gravatar', 'identicon' or 'none'. Default: 'none'.") do |mode|
|
"Can be set to 'gravatar' or 'identicon'. Default: standard avatar.") do |mode|
|
||||||
wiki_options[:user_icons] = mode
|
wiki_options[:user_icons] = mode.to_s
|
||||||
end
|
end
|
||||||
opts.on("--template-dir [PATH]", "Specify custom mustache template directory.") do |path|
|
opts.on("--template-dir [PATH]", "Specify custom mustache template directory.") do |path|
|
||||||
wiki_options[:template_dir] = path
|
wiki_options[:template_dir] = path
|
||||||
|
|||||||
+6
-4
@@ -17,6 +17,7 @@ require 'gollum/views/helpers'
|
|||||||
require 'gollum/views/layout'
|
require 'gollum/views/layout'
|
||||||
require 'gollum/views/editable'
|
require 'gollum/views/editable'
|
||||||
require 'gollum/views/has_page'
|
require 'gollum/views/has_page'
|
||||||
|
require 'gollum/views/has_user_icons'
|
||||||
require 'gollum/views/pagination'
|
require 'gollum/views/pagination'
|
||||||
|
|
||||||
|
|
||||||
@@ -397,11 +398,12 @@ module Precious
|
|||||||
end
|
end
|
||||||
|
|
||||||
get '/history/*' do
|
get '/history/*' do
|
||||||
wikip = wiki_page(params[:splat].first)
|
wikip = wiki_page(params[:splat].first)
|
||||||
@name = wikip.fullname
|
@name = wikip.fullname
|
||||||
@page = wikip.page
|
@page = wikip.page
|
||||||
@page_num = [params[:page_num].to_i, 1].max
|
@page_num = [params[:page_num].to_i, 1].max
|
||||||
@max_count = settings.wiki_options.fetch(:pagination_count, 10)
|
@max_count = settings.wiki_options.fetch(:pagination_count, 10)
|
||||||
|
@wiki = @page.wiki
|
||||||
unless @page.nil?
|
unless @page.nil?
|
||||||
@versions = @page.versions(
|
@versions = @page.versions(
|
||||||
per_page: @max_count,
|
per_page: @max_count,
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 376 B |
@@ -1,4 +1,5 @@
|
|||||||
//= require jquery-1.7.2.min
|
//= require jquery-1.7.2.min
|
||||||
|
//= require identicon
|
||||||
//= require mousetrap.min
|
//= require mousetrap.min
|
||||||
//= require gollum
|
//= require gollum
|
||||||
//= require gollum.dialog
|
//= require gollum.dialog
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
// Helpers
|
// Helpers
|
||||||
|
|
||||||
|
// Replace broken user icons with 'person' octicon
|
||||||
|
function brokenAvatarImage(image){
|
||||||
|
image.onerror = '';
|
||||||
|
image.src = 'data:image/svg+xml;utf8,<%= rocticon_css(:person) %>';
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Get path for named route, prefixing baseUrl if necessary
|
// Get path for named route, prefixing baseUrl if necessary
|
||||||
// Uses the route definitions in /lib/gollum/views/helpers.rb.
|
// Uses the route definitions in /lib/gollum/views/helpers.rb.
|
||||||
// For example, routePath('delete') is equivalent to 'delete_path' in the mustache templates.
|
// For example, routePath('delete') is equivalent to 'delete_path' in the mustache templates.
|
||||||
@@ -498,20 +505,17 @@ $(document).ready(function() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if( $('#wiki-history').length ){
|
if( $('#wiki-history').length || $('#page-history').length){
|
||||||
var lookup = {};
|
var options = {
|
||||||
|
format: 'svg',
|
||||||
|
background: [255, 255, 255, 255] // rgba white
|
||||||
|
};
|
||||||
$('img.identicon').each(function(index, element){
|
$('img.identicon').each(function(index, element){
|
||||||
var $item = $(element);
|
var item = $(element);
|
||||||
var code = parseInt($item.data('identicon'), 10);
|
var code = item.data('identicon');
|
||||||
var img_bin = lookup[code];
|
var img_bin = new Identicon(code, options).toString();
|
||||||
if( img_bin === undefined ){
|
img_bin = 'data:image/svg+xml;base64,' + img_bin;
|
||||||
var size = 16;
|
item.attr('src', img_bin);
|
||||||
var canvas = $('<canvas width=16 height=16/>').get(0);
|
|
||||||
render_identicon(canvas, code, 16);
|
|
||||||
img_bin = canvas.toDataURL("image/png");
|
|
||||||
lookup[code] = img_bin;
|
|
||||||
}
|
|
||||||
$item.attr('src', img_bin);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,205 @@
|
|||||||
|
/**
|
||||||
|
* Identicon.js 2.3.3
|
||||||
|
* http://github.com/stewartlord/identicon.js
|
||||||
|
*
|
||||||
|
* PNGLib required for PNG output
|
||||||
|
* http://www.xarg.org/download/pnglib.js
|
||||||
|
*
|
||||||
|
* Copyright 2018, Stewart Lord
|
||||||
|
* Released under the BSD license
|
||||||
|
* http://www.opensource.org/licenses/bsd-license.php
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
var PNGlib;
|
||||||
|
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
|
||||||
|
PNGlib = require('./pnglib');
|
||||||
|
} else {
|
||||||
|
PNGlib = window.PNGlib;
|
||||||
|
}
|
||||||
|
|
||||||
|
var Identicon = function(hash, options){
|
||||||
|
if (typeof(hash) !== 'string' || hash.length < 15) {
|
||||||
|
throw 'A hash of at least 15 characters is required.';
|
||||||
|
}
|
||||||
|
|
||||||
|
this.defaults = {
|
||||||
|
background: [240, 240, 240, 255],
|
||||||
|
margin: 0.08,
|
||||||
|
size: 64,
|
||||||
|
saturation: 0.7,
|
||||||
|
brightness: 0.5,
|
||||||
|
format: 'png'
|
||||||
|
};
|
||||||
|
|
||||||
|
this.options = typeof(options) === 'object' ? options : this.defaults;
|
||||||
|
|
||||||
|
// backward compatibility with old constructor (hash, size, margin)
|
||||||
|
if (typeof(arguments[1]) === 'number') { this.options.size = arguments[1]; }
|
||||||
|
if (arguments[2]) { this.options.margin = arguments[2]; }
|
||||||
|
|
||||||
|
this.hash = hash
|
||||||
|
this.background = this.options.background || this.defaults.background;
|
||||||
|
this.size = this.options.size || this.defaults.size;
|
||||||
|
this.format = this.options.format || this.defaults.format;
|
||||||
|
this.margin = this.options.margin !== undefined ? this.options.margin : this.defaults.margin;
|
||||||
|
|
||||||
|
// foreground defaults to last 7 chars as hue at 70% saturation, 50% brightness
|
||||||
|
var hue = parseInt(this.hash.substr(-7), 16) / 0xfffffff;
|
||||||
|
var saturation = this.options.saturation || this.defaults.saturation;
|
||||||
|
var brightness = this.options.brightness || this.defaults.brightness;
|
||||||
|
this.foreground = this.options.foreground || this.hsl2rgb(hue, saturation, brightness);
|
||||||
|
};
|
||||||
|
|
||||||
|
Identicon.prototype = {
|
||||||
|
background: null,
|
||||||
|
foreground: null,
|
||||||
|
hash: null,
|
||||||
|
margin: null,
|
||||||
|
size: null,
|
||||||
|
format: null,
|
||||||
|
|
||||||
|
image: function(){
|
||||||
|
return this.isSvg()
|
||||||
|
? new Svg(this.size, this.foreground, this.background)
|
||||||
|
: new PNGlib(this.size, this.size, 256);
|
||||||
|
},
|
||||||
|
|
||||||
|
render: function(){
|
||||||
|
var image = this.image(),
|
||||||
|
size = this.size,
|
||||||
|
baseMargin = Math.floor(size * this.margin),
|
||||||
|
cell = Math.floor((size - (baseMargin * 2)) / 5),
|
||||||
|
margin = Math.floor((size - cell * 5) / 2),
|
||||||
|
bg = image.color.apply(image, this.background),
|
||||||
|
fg = image.color.apply(image, this.foreground);
|
||||||
|
|
||||||
|
// the first 15 characters of the hash control the pixels (even/odd)
|
||||||
|
// they are drawn down the middle first, then mirrored outwards
|
||||||
|
var i, color;
|
||||||
|
for (i = 0; i < 15; i++) {
|
||||||
|
color = parseInt(this.hash.charAt(i), 16) % 2 ? bg : fg;
|
||||||
|
if (i < 5) {
|
||||||
|
this.rectangle(2 * cell + margin, i * cell + margin, cell, cell, color, image);
|
||||||
|
} else if (i < 10) {
|
||||||
|
this.rectangle(1 * cell + margin, (i - 5) * cell + margin, cell, cell, color, image);
|
||||||
|
this.rectangle(3 * cell + margin, (i - 5) * cell + margin, cell, cell, color, image);
|
||||||
|
} else if (i < 15) {
|
||||||
|
this.rectangle(0 * cell + margin, (i - 10) * cell + margin, cell, cell, color, image);
|
||||||
|
this.rectangle(4 * cell + margin, (i - 10) * cell + margin, cell, cell, color, image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return image;
|
||||||
|
},
|
||||||
|
|
||||||
|
rectangle: function(x, y, w, h, color, image){
|
||||||
|
if (this.isSvg()) {
|
||||||
|
image.rectangles.push({x: x, y: y, w: w, h: h, color: color});
|
||||||
|
} else {
|
||||||
|
var i, j;
|
||||||
|
for (i = x; i < x + w; i++) {
|
||||||
|
for (j = y; j < y + h; j++) {
|
||||||
|
image.buffer[image.index(i, j)] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// adapted from: https://gist.github.com/aemkei/1325937
|
||||||
|
hsl2rgb: function(h, s, b){
|
||||||
|
h *= 6;
|
||||||
|
s = [
|
||||||
|
b += s *= b < .5 ? b : 1 - b,
|
||||||
|
b - h % 1 * s * 2,
|
||||||
|
b -= s *= 2,
|
||||||
|
b,
|
||||||
|
b + h % 1 * s,
|
||||||
|
b + s
|
||||||
|
];
|
||||||
|
|
||||||
|
return[
|
||||||
|
s[ ~~h % 6 ] * 255, // red
|
||||||
|
s[ (h|16) % 6 ] * 255, // green
|
||||||
|
s[ (h|8) % 6 ] * 255 // blue
|
||||||
|
];
|
||||||
|
},
|
||||||
|
|
||||||
|
toString: function(raw){
|
||||||
|
// backward compatibility with old toString, default to base64
|
||||||
|
if (raw) {
|
||||||
|
return this.render().getDump();
|
||||||
|
} else {
|
||||||
|
return this.render().getBase64();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
isSvg: function(){
|
||||||
|
return this.format.match(/svg/i)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var Svg = function(size, foreground, background){
|
||||||
|
this.size = size;
|
||||||
|
this.foreground = this.color.apply(this, foreground);
|
||||||
|
this.background = this.color.apply(this, background);
|
||||||
|
this.rectangles = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
Svg.prototype = {
|
||||||
|
size: null,
|
||||||
|
foreground: null,
|
||||||
|
background: null,
|
||||||
|
rectangles: null,
|
||||||
|
|
||||||
|
color: function(r, g, b, a){
|
||||||
|
var values = [r, g, b].map(Math.round);
|
||||||
|
values.push((a >= 0) && (a <= 255) ? a/255 : 1);
|
||||||
|
return 'rgba(' + values.join(',') + ')';
|
||||||
|
},
|
||||||
|
|
||||||
|
getDump: function(){
|
||||||
|
var i,
|
||||||
|
xml,
|
||||||
|
rect,
|
||||||
|
fg = this.foreground,
|
||||||
|
bg = this.background,
|
||||||
|
stroke = this.size * 0.005;
|
||||||
|
|
||||||
|
xml = "<svg xmlns='http://www.w3.org/2000/svg'"
|
||||||
|
+ " width='" + this.size + "' height='" + this.size + "'"
|
||||||
|
+ " style='background-color:" + bg + ";'>"
|
||||||
|
+ "<g style='fill:" + fg + "; stroke:" + fg + "; stroke-width:" + stroke + ";'>";
|
||||||
|
|
||||||
|
for (i = 0; i < this.rectangles.length; i++) {
|
||||||
|
rect = this.rectangles[i];
|
||||||
|
if (rect.color == bg) continue;
|
||||||
|
xml += "<rect "
|
||||||
|
+ " x='" + rect.x + "'"
|
||||||
|
+ " y='" + rect.y + "'"
|
||||||
|
+ " width='" + rect.w + "'"
|
||||||
|
+ " height='" + rect.h + "'"
|
||||||
|
+ "/>";
|
||||||
|
}
|
||||||
|
xml += "</g></svg>"
|
||||||
|
|
||||||
|
return xml;
|
||||||
|
},
|
||||||
|
|
||||||
|
getBase64: function(){
|
||||||
|
if ('function' === typeof btoa) {
|
||||||
|
return btoa(this.getDump());
|
||||||
|
} else if (Buffer) {
|
||||||
|
return new Buffer(this.getDump(), 'binary').toString('base64');
|
||||||
|
} else {
|
||||||
|
throw 'Cannot generate base64 output';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
|
||||||
|
module.exports = Identicon;
|
||||||
|
} else {
|
||||||
|
window.Identicon = Identicon;
|
||||||
|
}
|
||||||
|
})();
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
/*
|
|
||||||
Client-side Canvas tag based Identicon rendering code
|
|
||||||
|
|
||||||
@author Don Park
|
|
||||||
@version 0.2
|
|
||||||
@date January 21th, 2007
|
|
||||||
*/
|
|
||||||
|
|
||||||
var patch0 = new Array( 0, 4, 24, 20 );
|
|
||||||
var patch1 = new Array( 0, 4, 20 );
|
|
||||||
var patch2 = new Array( 2, 24, 20 );
|
|
||||||
var patch3 = new Array( 0, 2, 20, 22 );
|
|
||||||
var patch4 = new Array( 2, 14, 22, 10 );
|
|
||||||
var patch5 = new Array( 0, 14, 24, 22 );
|
|
||||||
var patch6 = new Array( 2, 24, 22, 13, 11, 22, 20 );
|
|
||||||
var patch7 = new Array( 0, 14, 22 );
|
|
||||||
var patch8 = new Array( 6, 8, 18, 16 );
|
|
||||||
var patch9 = new Array( 4, 20, 10, 12, 2 );
|
|
||||||
var patch10 = new Array( 0, 2, 12, 10 );
|
|
||||||
var patch11 = new Array( 10, 14, 22 );
|
|
||||||
var patch12 = new Array( 20, 12, 24 );
|
|
||||||
var patch13 = new Array( 10, 2, 12 );
|
|
||||||
var patch14 = new Array( 0, 2, 10 );
|
|
||||||
var patchTypes = new Array( patch0, patch1, patch2, patch3, patch4,
|
|
||||||
patch5, patch6, patch7, patch8, patch9, patch10, patch11,
|
|
||||||
patch12, patch13, patch14, patch0 );
|
|
||||||
var centerPatchTypes = new Array(0, 4, 8, 15);
|
|
||||||
|
|
||||||
function render_identicon_patch(ctx, x, y, size, patch, turn, invert, foreColor, backColor) {
|
|
||||||
patch %= patchTypes.length;
|
|
||||||
turn %= 4;
|
|
||||||
if (patch == 15)
|
|
||||||
invert = !invert;
|
|
||||||
|
|
||||||
var vertices = patchTypes[patch];
|
|
||||||
var offset = size / 2;
|
|
||||||
var scale = size / 4;
|
|
||||||
|
|
||||||
ctx.save();
|
|
||||||
|
|
||||||
// paint background
|
|
||||||
ctx.fillStyle = invert ? foreColor : backColor;
|
|
||||||
ctx.fillRect(x, y, size, size);
|
|
||||||
|
|
||||||
// build patch path
|
|
||||||
ctx.translate(x + offset, y + offset);
|
|
||||||
ctx.rotate(turn * Math.PI / 2);
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.moveTo((vertices[0] % 5 * scale - offset), (Math.floor(vertices[0] / 5) * scale - offset));
|
|
||||||
for (var i = 1; i < vertices.length; i++)
|
|
||||||
ctx.lineTo((vertices[i] % 5 * scale - offset), (Math.floor(vertices[i] / 5) * scale - offset));
|
|
||||||
ctx.closePath();
|
|
||||||
|
|
||||||
// offset and rotate coordinate space by patch position (x, y) and
|
|
||||||
// 'turn' before rendering patch shape
|
|
||||||
|
|
||||||
// render rotated patch using fore color (back color if inverted)
|
|
||||||
ctx.fillStyle = invert ? backColor : foreColor;
|
|
||||||
ctx.fill();
|
|
||||||
|
|
||||||
// restore rotation
|
|
||||||
ctx.restore();
|
|
||||||
}
|
|
||||||
|
|
||||||
function render_identicon(node, code, size) {
|
|
||||||
if (!node || !code || !size) return;
|
|
||||||
|
|
||||||
var patchSize = size / 3;
|
|
||||||
var middleType = centerPatchTypes[code & 3];
|
|
||||||
var middleInvert = ((code >> 2) & 1) != 0;
|
|
||||||
var cornerType = (code >> 3) & 15;
|
|
||||||
var cornerInvert = ((code >> 7) & 1) != 0;
|
|
||||||
var cornerTurn = (code >> 8) & 3;
|
|
||||||
var sideType = (code >> 10) & 15;
|
|
||||||
var sideInvert = ((code >> 14) & 1) != 0;
|
|
||||||
var sideTurn = (code >> 15) & 3;
|
|
||||||
var blue = (code >> 16) & 31;
|
|
||||||
var green = (code >> 21) & 31;
|
|
||||||
var red = (code >> 27) & 31;
|
|
||||||
var foreColor = "rgb(" + (red << 3) + "," + (green << 3) + "," + (blue << 3) + ")";
|
|
||||||
var backColor = "rgb(255,255,255)";
|
|
||||||
|
|
||||||
var ctx = node.getContext("2d");
|
|
||||||
|
|
||||||
// middle patch
|
|
||||||
render_identicon_patch(ctx, patchSize, patchSize, patchSize, middleType, 0, middleInvert, foreColor, backColor);
|
|
||||||
// side patchs, starting from top and moving clock-wise
|
|
||||||
render_identicon_patch(ctx, patchSize, 0, patchSize, sideType, sideTurn++, sideInvert, foreColor, backColor);
|
|
||||||
render_identicon_patch(ctx, patchSize * 2, patchSize, patchSize, sideType, sideTurn++, sideInvert, foreColor, backColor);
|
|
||||||
render_identicon_patch(ctx, patchSize, patchSize * 2, patchSize, sideType, sideTurn++, sideInvert, foreColor, backColor);
|
|
||||||
render_identicon_patch(ctx, 0, patchSize, patchSize, sideType, sideTurn++, sideInvert, foreColor, backColor);
|
|
||||||
// corner patchs, starting from top left and moving clock-wise
|
|
||||||
render_identicon_patch(ctx, 0, 0, patchSize, cornerType, cornerTurn++, cornerInvert, foreColor, backColor);
|
|
||||||
render_identicon_patch(ctx, patchSize * 2, 0, patchSize, cornerType, cornerTurn++, cornerInvert, foreColor, backColor);
|
|
||||||
render_identicon_patch(ctx, patchSize * 2, patchSize * 2, patchSize, cornerType, cornerTurn++, cornerInvert, foreColor, backColor);
|
|
||||||
render_identicon_patch(ctx, 0, patchSize * 2, patchSize, cornerType, cornerTurn++, cornerInvert, foreColor, backColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
function render_identicon_canvases(prefix) {
|
|
||||||
var canvases = document.getElementsByTagName("canvas");
|
|
||||||
var n = canvases.length;
|
|
||||||
for (var i = 0; i < n; i++) {
|
|
||||||
var node = canvases[i];
|
|
||||||
if (node.title && node.title.indexOf(prefix) == 0) {
|
|
||||||
if (node.style.display == 'none') node.style.display = "inline";
|
|
||||||
var code = node.title.substring(prefix.length) * 1;
|
|
||||||
var size = node.width;
|
|
||||||
render_identicon(node, code, size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,6 +2,15 @@
|
|||||||
|
|
||||||
/* @section history */
|
/* @section history */
|
||||||
|
|
||||||
|
#user-icons {
|
||||||
|
a, img, span, svg {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
img, svg {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.history #footer {
|
.history #footer {
|
||||||
margin-bottom: 7em;
|
margin-bottom: 7em;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
{{#versions}}
|
{{#versions}}
|
||||||
<li class="Box-row border-top Box-row--hover-gray d-flex flex-items-center">
|
<li class="Box-row border-top Box-row--hover-gray d-flex flex-items-center">
|
||||||
<span class="pr-2"><input class="checkbox" type="checkbox" name="versions[]" value="{{id}}"></span>
|
<span class="pr-2"><input class="checkbox" type="checkbox" name="versions[]" value="{{id}}"></span>
|
||||||
<span class="float-left col-2">{{>author_template}}</span>
|
<span class="float-left col-2" id="user-icons">{{>author_template}}</span>
|
||||||
<span class="flex-auto col-1 text-gray-light">{{date}}</span>
|
<span class="flex-auto col-1 text-gray-light">{{date}}</span>
|
||||||
<span class="flex-auto col-5">{{message}}</span>
|
<span class="flex-auto col-5">{{message}}</span>
|
||||||
<span class="pl-4 float-right">[<a href="{{base_url}}/{{escaped_url_path}}/{{id}}" title="View commit">{{id7}}</a>]</span>
|
<span class="pl-4 float-right">[<a href="{{base_url}}/{{escaped_url_path}}/{{id}}" title="View commit">{{id7}}</a>]</span>
|
||||||
|
|||||||
@@ -1,5 +1,2 @@
|
|||||||
<a href="javascript:void(0)">
|
<img src="https://secure.gravatar.com/avatar/{{user_icon}}?s=20" class="mini-gravatar" onerror="brokenAvatarImage(this);" />
|
||||||
<img src="https://secure.gravatar.com/avatar/{{gravatar}}?s=16"
|
<a href="https://gravatar.com/{{user_icon}}">{{author}}</a>
|
||||||
alt="avatar: {{author}}" class="mini-gravatar"/>
|
|
||||||
{{author}}
|
|
||||||
</a>
|
|
||||||
@@ -1,5 +1,2 @@
|
|||||||
<a href="javascript:void(0)">
|
<img src="" alt="avatar: {{author}}" class="identicon" data-identicon="{{user_icon}}" onerror="brokenAvatarImage(this);" />
|
||||||
<img src="{{#sprockets_image_path}}man_24.png{{/sprockets_image_path}}" alt="avatar: {{author}}"
|
<span>{{author}}</span>
|
||||||
class="mini-gravatar identicon" data-identicon="{{identicon}}"/>
|
|
||||||
{{author}}
|
|
||||||
</a>
|
|
||||||
@@ -1 +1,2 @@
|
|||||||
{{author}}
|
{{#octicon}}person{{/octicon}}
|
||||||
|
<span>{{author}}</span>
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
<div class="Box flex-auto">
|
<div class="Box flex-auto">
|
||||||
{{#versions}}
|
{{#versions}}
|
||||||
<div class="Box-row Box-row--hover-gray border-top d-flex flex-items-center">
|
<div class="Box-row Box-row--hover-gray border-top d-flex flex-items-center">
|
||||||
<span class="float-left col-2">{{>author_template}}</span>
|
<span class="float-left col-2" id="user-icons">{{>author_template}}</span>
|
||||||
<span class="flex-auto col-1 text-gray-light">{{date}}</span>
|
<span class="flex-auto col-1 text-gray-light">{{date}}</span>
|
||||||
<span class="flex-auto col-7">{{message}}<br/>
|
<span class="flex-auto col-7">{{message}}<br/>
|
||||||
{{#files}}
|
{{#files}}
|
||||||
|
|||||||
@@ -26,9 +26,6 @@
|
|||||||
|
|
||||||
</script>
|
</script>
|
||||||
{{#sprockets_javascript_tag}}app{{/sprockets_javascript_tag}}
|
{{#sprockets_javascript_tag}}app{{/sprockets_javascript_tag}}
|
||||||
{{#use_identicon}}
|
|
||||||
{{#sprockets_javascript_tag}}identicon_canvas{{/sprockets_javascript_tag}}
|
|
||||||
{{/use_identicon}}
|
|
||||||
{{#mathjax}}
|
{{#mathjax}}
|
||||||
{{^mathjax_config}}
|
{{^mathjax_config}}
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
module Precious
|
||||||
|
module HasUserIcons
|
||||||
|
def user_icon_code(str)
|
||||||
|
Digest::MD5.hexdigest(str.strip.downcase)
|
||||||
|
end
|
||||||
|
|
||||||
|
def partial(name)
|
||||||
|
if name == :author_template
|
||||||
|
self.class.partial("history_authors/#{@wiki.user_icons}")
|
||||||
|
else
|
||||||
|
super
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -3,6 +3,7 @@ module Precious
|
|||||||
class History < Layout
|
class History < Layout
|
||||||
include HasPage
|
include HasPage
|
||||||
include Pagination
|
include Pagination
|
||||||
|
include HasUserIcons
|
||||||
include Sprockets::Helpers
|
include Sprockets::Helpers
|
||||||
include Precious::Views::SprocketsHelpers
|
include Precious::Views::SprocketsHelpers
|
||||||
|
|
||||||
@@ -23,49 +24,11 @@ module Precious
|
|||||||
:author => v.author.name.respond_to?(:force_encoding) ? v.author.name.force_encoding('UTF-8') : v.author.name,
|
:author => v.author.name.respond_to?(:force_encoding) ? v.author.name.force_encoding('UTF-8') : v.author.name,
|
||||||
:message => v.message.respond_to?(:force_encoding) ? v.message.force_encoding('UTF-8') : v.message,
|
:message => v.message.respond_to?(:force_encoding) ? v.message.force_encoding('UTF-8') : v.message,
|
||||||
:date => v.authored_date.strftime("%B %d, %Y"),
|
:date => v.authored_date.strftime("%B %d, %Y"),
|
||||||
:gravatar => Digest::MD5.hexdigest(v.author.email.strip.downcase),
|
:user_icon => self.user_icon_code(v.author.email),
|
||||||
:identicon => self._identicon_code(v.author.email),
|
|
||||||
:date_full => v.authored_date,
|
:date_full => v.authored_date,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# http://stackoverflow.com/questions/9445760/bit-shifting-in-ruby
|
|
||||||
def left_shift int, shift
|
|
||||||
r = ((int & 0xFF) << (shift & 0x1F)) & 0xFFFFFFFF
|
|
||||||
# 1>>31, 2**32
|
|
||||||
(r & 2147483648) == 0 ? r : r - 4294967296
|
|
||||||
end
|
|
||||||
|
|
||||||
def string_to_code string
|
|
||||||
# sha bytes
|
|
||||||
b = [Digest::SHA1.hexdigest(string)[0, 20]].pack('H*').bytes.to_a
|
|
||||||
# Thanks donpark's IdenticonUtil.java for this.
|
|
||||||
# Match the following Java code
|
|
||||||
# ((b[0] & 0xFF) << 24) | ((b[1] & 0xFF) << 16) |
|
|
||||||
# ((b[2] & 0xFF) << 8) | (b[3] & 0xFF)
|
|
||||||
|
|
||||||
return left_shift(b[0], 24) |
|
|
||||||
left_shift(b[1], 16) |
|
|
||||||
left_shift(b[2], 8) |
|
|
||||||
b[3] & 0xFF
|
|
||||||
end
|
|
||||||
|
|
||||||
def _identicon_code(blob)
|
|
||||||
string_to_code blob + @request.host
|
|
||||||
end
|
|
||||||
|
|
||||||
def use_identicon
|
|
||||||
@page.wiki.user_icons == 'identicon'
|
|
||||||
end
|
|
||||||
|
|
||||||
def partial(name)
|
|
||||||
if name == :author_template
|
|
||||||
self.class.partial("history_authors/#{@page.wiki.user_icons}")
|
|
||||||
else
|
|
||||||
super
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def editable
|
def editable
|
||||||
@editable
|
@editable
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ module Precious
|
|||||||
module Views
|
module Views
|
||||||
class LatestChanges < Layout
|
class LatestChanges < Layout
|
||||||
include Pagination
|
include Pagination
|
||||||
|
include HasUserIcons
|
||||||
|
|
||||||
attr_reader :wiki
|
attr_reader :wiki
|
||||||
|
|
||||||
@@ -19,8 +20,7 @@ module Precious
|
|||||||
:author => v.author.name.respond_to?(:force_encoding) ? v.author.name.force_encoding('UTF-8') : v.author.name,
|
:author => v.author.name.respond_to?(:force_encoding) ? v.author.name.force_encoding('UTF-8') : v.author.name,
|
||||||
:message => v.message.respond_to?(:force_encoding) ? v.message.force_encoding('UTF-8') : v.message,
|
:message => v.message.respond_to?(:force_encoding) ? v.message.force_encoding('UTF-8') : v.message,
|
||||||
:date => v.authored_date.strftime("%B %d, %Y"),
|
:date => v.authored_date.strftime("%B %d, %Y"),
|
||||||
:gravatar => Digest::MD5.hexdigest(v.author.email.strip.downcase),
|
:user_icon => self.user_icon_code(v.author.email),
|
||||||
:identicon => self._identicon_code(v.author.email),
|
|
||||||
:date_full => v.authored_date,
|
:date_full => v.authored_date,
|
||||||
:files => v.stats.files.map { |f,*rest|
|
:files => v.stats.files.map { |f,*rest|
|
||||||
page_path = extract_renamed_path_destination(f)
|
page_path = extract_renamed_path_destination(f)
|
||||||
@@ -36,43 +36,6 @@ module Precious
|
|||||||
return file.gsub(/{.* => (.*)}/, '\1').gsub(/.* => (.*)/, '\1')
|
return file.gsub(/{.* => (.*)}/, '\1').gsub(/.* => (.*)/, '\1')
|
||||||
end
|
end
|
||||||
|
|
||||||
# http://stackoverflow.com/questions/9445760/bit-shifting-in-ruby
|
|
||||||
def left_shift(int, shift)
|
|
||||||
r = ((int & 0xFF) << (shift & 0x1F)) & 0xFFFFFFFF
|
|
||||||
# 1>>31, 2**32
|
|
||||||
(r & 2147483648) == 0 ? r : r - 4294967296
|
|
||||||
end
|
|
||||||
|
|
||||||
def string_to_code(string)
|
|
||||||
# sha bytes
|
|
||||||
b = [Digest::SHA1.hexdigest(string)[0, 20]].pack('H*').bytes.to_a
|
|
||||||
# Thanks donpark's IdenticonUtil.java for this.
|
|
||||||
# Match the following Java code
|
|
||||||
# ((b[0] & 0xFF) << 24) | ((b[1] & 0xFF) << 16) |
|
|
||||||
# ((b[2] & 0xFF) << 8) | (b[3] & 0xFF)
|
|
||||||
|
|
||||||
return left_shift(b[0], 24) |
|
|
||||||
left_shift(b[1], 16) |
|
|
||||||
left_shift(b[2], 8) |
|
|
||||||
b[3] & 0xFF
|
|
||||||
end
|
|
||||||
|
|
||||||
def _identicon_code(blob)
|
|
||||||
string_to_code blob + @request.host
|
|
||||||
end
|
|
||||||
|
|
||||||
def use_identicon
|
|
||||||
@wiki.user_icons == 'identicon'
|
|
||||||
end
|
|
||||||
|
|
||||||
def partial(name)
|
|
||||||
if name == :author_template
|
|
||||||
self.class.partial("history_authors/#{@wiki.user_icons}")
|
|
||||||
else
|
|
||||||
super
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def previous_link
|
def previous_link
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
The MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2010 Ryan Seddon
|
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
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 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.
|
|
||||||
|
|
||||||
=============================================================================
|
|
||||||
|
|
||||||
BSD License
|
|
||||||
|
|
||||||
Copyright (c) 2010, Ryan Seddon
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
1. Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer in the
|
|
||||||
documentation and/or other materials provided with the distribution.
|
|
||||||
3. Neither the name of the organization nor the
|
|
||||||
names of its contributors may be used to endorse or promote products
|
|
||||||
derived from this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY COPYRIGHT HOLDER "AS IS" AND ANY
|
|
||||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER BE LIABLE FOR ANY
|
|
||||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
+5
-41
@@ -7,48 +7,12 @@ gollum is not permitted.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
The following PNGs are based on Ubuntu 11.10 SVG files located in /usr/share/icons/unity-icon-theme/places/svg/
|
The identicon.js code is used under the BSD license.
|
||||||
- group-folders.svg
|
|
||||||
- group-files.svg
|
|
||||||
- group-downloads.svg
|
|
||||||
|
|
||||||
lib/gollum/public/css/document.png
|
https://github.com/stewartlord/identicon.js/blob/master/identicon.js
|
||||||
lib/gollum/public/css/folder-horizontal.png
|
https://github.com/stewartlord/identicon.js/blob/master/README.md
|
||||||
lib/gollum/public/css/toggle-small-expand.png
|
|
||||||
lib/gollum/public/css/toggle-small.png
|
lib/gollum/public/gollum/javascript/identicon.js
|
||||||
|
|
||||||
Creative Commons - Attribution Share Alike
|
|
||||||
https://launchpad.net/unity-asset-pool
|
|
||||||
http://packages.ubuntu.com/oneiric/all/unity-asset-pool/filelist
|
|
||||||
https://bazaar.launchpad.net/~unity-team/unity-asset-pool/trunk/view/head:/COPYRIGHT
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
The css-tree-menu code is used under the MIT license.
|
|
||||||
|
|
||||||
http://www.thecssninja.com/css/css-tree-menu
|
|
||||||
http://www.thecssninja.com/demo/license.txt
|
|
||||||
|
|
||||||
lib/gollum/public/css/_styles.css
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Default profile image (man_24.png) is used under the CC BY-SA 3.0 Unported license.
|
|
||||||
|
|
||||||
CC BY-SA 3.0 Unported
|
|
||||||
http://blog.twg.ca/2010/11/retina-display-icon-set/
|
|
||||||
http://creativecommons.org/licenses/by-sa/3.0/legalcode.txt
|
|
||||||
|
|
||||||
lib/gollum/public/images/man_24.png
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
The canvas_identicon code is used under the MIT license.
|
|
||||||
|
|
||||||
https://github.com/donpark/identicon/blob/master/identicon-canvas/identicon_canvas.js
|
|
||||||
https://github.com/donpark/identicon/blob/master/README
|
|
||||||
|
|
||||||
lib/gollum/public/gollum/javascript/identicon_canvas.js
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,286 +0,0 @@
|
|||||||
This package was debianized by Kenneth Wimer <kwwii@ubuntu.com> on
|
|
||||||
Fri, 12 Dec 2010 9:08:32 +0200.
|
|
||||||
|
|
||||||
Upstream Author:
|
|
||||||
Michael Forrest <michael.forrest@canonical.com>
|
|
||||||
Otto Greenslade <otto.greenslade@canonical.com>
|
|
||||||
|
|
||||||
Copyright:
|
|
||||||
|
|
||||||
(c) Canonical Ltd 2004- 2009
|
|
||||||
|
|
||||||
Unless otherwise indicated, artwork is available under the Creative
|
|
||||||
Commons Attribution Share-alike license v3.0 or any later version. To
|
|
||||||
view a copy of this license, visit
|
|
||||||
http://creativecommons.org/licenses/by-sa/3.0/ or send a letter to
|
|
||||||
Creative Commons, 171 Second Street, Suite 300, San Francisco,
|
|
||||||
California, 94105, USA. See below for the full text of the license.
|
|
||||||
|
|
||||||
Some Rights Reserved:
|
|
||||||
|
|
||||||
The rights in the trademarks, logos, service marks of Canonical Ltd,
|
|
||||||
as well as the look and feel of Ubuntu, are not licensed under the
|
|
||||||
Creative Commons license and are subject to the Canonical Trademark
|
|
||||||
Policy at http://www.ubuntu.com/ubuntu/TrademarkPolicy
|
|
||||||
|
|
||||||
License:
|
|
||||||
|
|
||||||
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
|
||||||
LEGAL SERVICES. DISTRIBUTION OF THIS LICENSE DOES NOT CREATE AN
|
|
||||||
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
|
||||||
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
|
||||||
REGARDING THE INFORMATION PROVIDED, AND DISCLAIMS LIABILITY FOR
|
|
||||||
DAMAGES RESULTING FROM ITS USE.
|
|
||||||
|
|
||||||
License
|
|
||||||
|
|
||||||
THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS
|
|
||||||
CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS
|
|
||||||
PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE
|
|
||||||
WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW
|
|
||||||
IS PROHIBITED.
|
|
||||||
|
|
||||||
BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND
|
|
||||||
AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. THE LICENSOR GRANTS YOU
|
|
||||||
THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH
|
|
||||||
TERMS AND CONDITIONS.
|
|
||||||
|
|
||||||
1. Definitions
|
|
||||||
|
|
||||||
1. "Collective Work" means a work, such as a periodical issue,
|
|
||||||
anthology or encyclopedia, in which the Work in its entirety in
|
|
||||||
unmodified form, along with a number of other contributions,
|
|
||||||
constituting separate and independent works in themselves, are
|
|
||||||
assembled into a collective whole. A work that constitutes a
|
|
||||||
Collective Work will not be considered a Derivative Work
|
|
||||||
(as defined below) for the purposes of this License.
|
|
||||||
2. "Derivative Work" means a work based upon the Work or upon the
|
|
||||||
Work and other pre-existing works, such as a translation, musical
|
|
||||||
arrangement, dramatization, fictionalization, motion picture
|
|
||||||
version, sound recording, art reproduction, abridgment,
|
|
||||||
condensation, or any other form in which the Work may be recast,
|
|
||||||
transformed, or adapted, except that a work that constitutes a
|
|
||||||
Collective Work will not be considered a Derivative Work for the
|
|
||||||
purpose of this License. For the avoidance of doubt, where the Work
|
|
||||||
is a musical composition or sound recording, the synchronization of
|
|
||||||
the Work in timed-relation with a moving image ("synching") will be
|
|
||||||
considered a Derivative Work for the purpose of this License.
|
|
||||||
3. "Licensor" means the individual or entity that offers the Work
|
|
||||||
under the terms of this License.
|
|
||||||
4. "Original Author" means the individual or entity who created the
|
|
||||||
Work.
|
|
||||||
5. "Work" means the copyrightable work of authorship offered under
|
|
||||||
the terms of this License.
|
|
||||||
6. "You" means an individual or entity exercising rights under this
|
|
||||||
License who has not previously violated the terms of this License
|
|
||||||
with respect to the Work, or who has received express permission
|
|
||||||
from the Licensor to exercise rights under this License despite a
|
|
||||||
previous violation.
|
|
||||||
7. "License Elements" means the following high-level license
|
|
||||||
attributes as selected by Licensor and indicated in the title of
|
|
||||||
this License: Attribution, ShareAlike.
|
|
||||||
|
|
||||||
2. Fair Use Rights. Nothing in this license is intended to reduce,
|
|
||||||
limit, or restrict any rights arising from fair use, first sale or
|
|
||||||
other limitations on the exclusive rights of the copyright owner under
|
|
||||||
copyright law or other applicable laws.
|
|
||||||
|
|
||||||
3. License Grant. Subject to the terms and conditions of this License,
|
|
||||||
Licensor hereby grants You a worldwide, royalty-free, non-exclusive,
|
|
||||||
perpetual (for the duration of the applicable copyright) license to
|
|
||||||
exercise the rights in the Work as stated below:
|
|
||||||
|
|
||||||
1. to reproduce the Work, to incorporate the Work into one or more
|
|
||||||
Collective Works, and to reproduce the Work as incorporated in the
|
|
||||||
Collective Works;
|
|
||||||
2. to create and reproduce Derivative Works;
|
|
||||||
3. to distribute copies or phonorecords of, display publicly,
|
|
||||||
perform publicly, and perform publicly by means of a digital audio
|
|
||||||
transmission the Work including as incorporated in Collective Works;
|
|
||||||
4. to distribute copies or phonorecords of, display publicly,
|
|
||||||
perform publicly, and perform publicly by means of a digital audio
|
|
||||||
transmission Derivative Works.
|
|
||||||
5.
|
|
||||||
|
|
||||||
For the avoidance of doubt, where the work is a musical
|
|
||||||
composition:
|
|
||||||
1. Performance Royalties Under Blanket Licenses. Licensor
|
|
||||||
waives the exclusive right to collect, whether individually
|
|
||||||
or via a performance rights society (e.g. ASCAP, BMI, SESAC),
|
|
||||||
royalties for the public performance or public digital
|
|
||||||
performance (e.g. webcast) of the Work.
|
|
||||||
2. Mechanical Rights and Statutory Royalties. Licensor waives
|
|
||||||
the exclusive right to collect, whether individually or via a
|
|
||||||
music rights society or designated agent (e.g. Harry Fox
|
|
||||||
Agency), royalties for any phonorecord You create from the
|
|
||||||
Work ("cover version") and distribute, subject to the
|
|
||||||
compulsory license created by 17 USC Section 115 of the US
|
|
||||||
Copyright Act (or the equivalent in other jurisdictions).
|
|
||||||
6. Webcasting Rights and Statutory Royalties. For the avoidance of
|
|
||||||
doubt, where the Work is a sound recording, Licensor waives the
|
|
||||||
exclusive right to collect, whether individually or via a
|
|
||||||
performance-rights society (e.g. SoundExchange), royalties for the
|
|
||||||
public digital performance (e.g. webcast) of the Work, subject to
|
|
||||||
the compulsory license created by 17 USC Section 114 of the US
|
|
||||||
Copyright Act (or the equivalent in other jurisdictions).
|
|
||||||
|
|
||||||
The above rights may be exercised in all media and formats whether now
|
|
||||||
known or hereafter devised. The above rights include the right to make
|
|
||||||
such modifications as are technically necessary to exercise the rights
|
|
||||||
in other media and formats. All rights not expressly granted by
|
|
||||||
Licensor are hereby reserved.
|
|
||||||
|
|
||||||
4. Restrictions.The license granted in Section 3 above is expressly
|
|
||||||
made subject to and limited by the following restrictions:
|
|
||||||
|
|
||||||
1. You may distribute, publicly display, publicly perform, or
|
|
||||||
publicly digitally perform the Work only under the terms of this
|
|
||||||
License, and You must include a copy of, or the Uniform Resource
|
|
||||||
Identifier for, this License with every copy or phonorecord of the
|
|
||||||
Work You distribute, publicly display, publicly perform, or publicly
|
|
||||||
digitally perform. You may not offer or impose any terms on the Work
|
|
||||||
that alter or restrict the terms of this License or the recipients'
|
|
||||||
exercise of the rights granted hereunder. You may not sublicense the
|
|
||||||
Work. You must keep intact all notices that refer to this License
|
|
||||||
and to the disclaimer of warranties. You may not distribute,
|
|
||||||
publicly display, publicly perform, or publicly digitally perform
|
|
||||||
the Work with any technological measures that control access or use
|
|
||||||
of the Work in a manner inconsistent with the terms of this License
|
|
||||||
Agreement. The above applies to the Work as incorporated in a
|
|
||||||
Collective Work, but this does not require the Collective Work apart
|
|
||||||
from the Work itself to be made subject to the terms of this
|
|
||||||
License. If You create a Collective Work, upon notice from any
|
|
||||||
Licensor You must, to the extent practicable, remove from the
|
|
||||||
Collective Work any credit as required by clause 4(c), as requested.
|
|
||||||
If You create a Derivative Work, upon notice from any Licensor You
|
|
||||||
must, to the extent practicable, remove from the Derivative Work
|
|
||||||
any credit as required by clause 4(c), as requested.
|
|
||||||
2. You may distribute, publicly display, publicly perform, or
|
|
||||||
publicly digitally perform a Derivative Work only under the terms
|
|
||||||
of this License, a later version of this License with the same
|
|
||||||
License Elements as this License, or a Creative Commons iCommons
|
|
||||||
license that contains the same License Elements as this License
|
|
||||||
(e.g. Attribution-ShareAlike 2.5 Japan). You must include a copy of,
|
|
||||||
or the Uniform Resource Identifier for, this License or other
|
|
||||||
license specified in the previous sentence with every copy or
|
|
||||||
phonorecord of each Derivative Work You distribute, publicly
|
|
||||||
display, publicly perform, or publicly digitally perform. You may
|
|
||||||
not offer or impose any terms on the Derivative Works that alter or
|
|
||||||
restrict the terms of this License or the recipients' exercise of
|
|
||||||
the rights granted hereunder, and You must keep intact all notices
|
|
||||||
that refer to this License and to the disclaimer of warranties.
|
|
||||||
You may not distribute, publicly display, publicly perform, or
|
|
||||||
publicly digitally perform the Derivative Work with any
|
|
||||||
technological measures that control access or use of the Work in a
|
|
||||||
manner inconsistent with the terms of this License Agreement.
|
|
||||||
The above applies to the Derivative Work as incorporated in a
|
|
||||||
Collective Work, but this does not require the Collective Work
|
|
||||||
apart from the Derivative Work itself to be made subject to the
|
|
||||||
terms of this License.
|
|
||||||
3. If you distribute, publicly display, publicly perform, or
|
|
||||||
publicly digitally perform the Work or any Derivative Works or
|
|
||||||
Collective Works, You must keep intact all copyright notices for
|
|
||||||
the Work and provide, reasonable to the medium or means You are
|
|
||||||
utilizing: (i) the name of the Original Author (or pseudonym, if
|
|
||||||
applicable) if supplied, and/or (ii) if the Original Author and/or
|
|
||||||
Licensor designate another party or parties (e.g. a sponsor
|
|
||||||
institute, publishing entity, journal) for attribution in Licensor's
|
|
||||||
copyright notice, terms of service or by other reasonable means, the
|
|
||||||
name of such party or parties; the title of the Work if supplied; to
|
|
||||||
the extent reasonably practicable, the Uniform Resource Identifier,
|
|
||||||
if any, that Licensor specifies to be associated with the Work,
|
|
||||||
unless such URI does not refer to the copyright notice or licensing
|
|
||||||
information for the Work; and in the case of a Derivative Work, a
|
|
||||||
credit identifying the use of the Work in the Derivative Work (e.g.,
|
|
||||||
"French translation of the Work by Original Author," or "Screenplay
|
|
||||||
based on original Work by Original Author"). Such credit may be
|
|
||||||
implemented in any reasonable manner; provided, however, that in the
|
|
||||||
case of a Derivative Work or Collective Work, at a minimum such
|
|
||||||
credit will appear where any other comparable authorship credit
|
|
||||||
appears and in a manner at least as prominent as such other
|
|
||||||
comparable authorship credit.
|
|
||||||
|
|
||||||
5. Representations, Warranties and Disclaimer
|
|
||||||
|
|
||||||
UNLESS OTHERWISE AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS
|
|
||||||
THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND
|
|
||||||
CONCERNING THE MATERIALS, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE,
|
|
||||||
INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF
|
|
||||||
LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF
|
|
||||||
ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW
|
|
||||||
THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY
|
|
||||||
TO YOU.
|
|
||||||
|
|
||||||
6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE
|
|
||||||
LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR
|
|
||||||
ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES
|
|
||||||
ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR
|
|
||||||
HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
|
||||||
|
|
||||||
7. Termination
|
|
||||||
|
|
||||||
1. This License and the rights granted hereunder will terminate
|
|
||||||
automatically upon any breach by You of the terms of this License.
|
|
||||||
Individuals or entities who have received Derivative Works or
|
|
||||||
Collective Works from You under this License, however, will not have
|
|
||||||
their licenses terminated provided such individuals or entities
|
|
||||||
remain in full compliance with those licenses. Sections 1, 2, 5, 6,
|
|
||||||
7, and 8 will survive any termination of this License.
|
|
||||||
2. Subject to the above terms and conditions, the license granted
|
|
||||||
here is perpetual (for the duration of the applicable copyright in
|
|
||||||
the Work). Notwithstanding the above, Licensor reserves the right to
|
|
||||||
release the Work under different license terms or to stop
|
|
||||||
distributing the Work at any time; provided, however that any such
|
|
||||||
election will not serve to withdraw this License (or any other
|
|
||||||
license that has been, or is required to be, granted under the terms
|
|
||||||
of this License), and this License will continue in full force and
|
|
||||||
effect unless terminated as stated above.
|
|
||||||
|
|
||||||
8. Miscellaneous
|
|
||||||
|
|
||||||
1. Each time You distribute or publicly digitally perform the Work
|
|
||||||
or a Collective Work, the Licensor offers to the recipient a license
|
|
||||||
to the Work on the same terms and conditions as the license granted
|
|
||||||
to You under this License.
|
|
||||||
2. Each time You distribute or publicly digitally perform a
|
|
||||||
Derivative Work, Licensor offers to the recipient a license to the
|
|
||||||
original Work on the same terms and conditions as the license
|
|
||||||
granted to You under this License.
|
|
||||||
3. If any provision of this License is invalid or unenforceable under
|
|
||||||
applicable law, it shall not affect the validity or enforceability of
|
|
||||||
the remainder of the terms of this License, and without further
|
|
||||||
action by the parties to this agreement, such provision shall be
|
|
||||||
reformed to the minimum extent necessary to make such provision
|
|
||||||
valid and enforceable.
|
|
||||||
4. No term or provision of this License shall be deemed waived and
|
|
||||||
no breach consented to unless such waiver or consent shall be in
|
|
||||||
writing and signed by the party to be charged with such waiver or
|
|
||||||
consent.
|
|
||||||
5. This License constitutes the entire agreement between the parties
|
|
||||||
with respect to the Work licensed here. There are no understandings,
|
|
||||||
agreements or representations with respect to the Work not specified
|
|
||||||
here. Licensor shall not be bound by any additional provisions that
|
|
||||||
may appear in any communication from You. This License may not be
|
|
||||||
modified without the mutual written agreement of the Licensor and
|
|
||||||
You.
|
|
||||||
|
|
||||||
Creative Commons is not a party to this License, and makes no warranty
|
|
||||||
whatsoever in connection with the Work. Creative Commons will not be
|
|
||||||
liable to You or any party on any legal theory for any damages
|
|
||||||
whatsoever, including without limitation any general, special,
|
|
||||||
incidental or consequential damages arising in connection to this
|
|
||||||
license. Notwithstanding the foregoing two (2) sentences, if Creative
|
|
||||||
Commons has expressly identified itself as the Licensor hereunder,
|
|
||||||
it shall have all rights and obligations of Licensor.
|
|
||||||
|
|
||||||
Except for the limited purpose of indicating to the public that the
|
|
||||||
Work is licensed under the CCPL, neither party will use the trademark
|
|
||||||
"Creative Commons" or any related trademark or logo of Creative Commons
|
|
||||||
without the prior written consent of Creative Commons. Any permitted
|
|
||||||
use will be in compliance with Creative Commons' then-current trademark
|
|
||||||
usage guidelines, as may be published on its website or otherwise made
|
|
||||||
available upon request from time to time.
|
|
||||||
|
|
||||||
Creative Commons may be contacted at http://creativecommons.org/
|
|
||||||
|
|
||||||
+1
-1
@@ -54,7 +54,7 @@ context "Frontend" do
|
|||||||
{ :name => 'user1', :email => 'user1' });
|
{ :name => 'user1', :email => 'user1' });
|
||||||
|
|
||||||
get page
|
get page
|
||||||
expected = "<h2 class=\"editable\"><a class=\"anchor\" (href|id)=\"(#)?#{text}\" (href|id)=\"(#)?#{text}\"><i class=\"fa fa-link\"></i></a>#{text}</h2>"
|
expected = "<h2 class=\"editable\"><a class=\"anchor\" (href|id)=\"(#)?#{text}\" (href|id)=\"(#)?#{text}\"></a>#{text}</h2>"
|
||||||
actual = nfd(last_response.body)
|
actual = nfd(last_response.body)
|
||||||
|
|
||||||
assert_match /#{expected}/, actual
|
assert_match /#{expected}/, actual
|
||||||
|
|||||||
@@ -7,19 +7,5 @@ context "Precious::Views::History" do
|
|||||||
@history = Precious::Views::History.new
|
@history = Precious::Views::History.new
|
||||||
end
|
end
|
||||||
|
|
||||||
test "string_to_code" do
|
# No tests yet
|
||||||
# Result must match the following Java code.
|
|
||||||
=begin
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
final String s = "code@example.com";
|
|
||||||
final byte[] b = MessageDigest.getInstance("SHA1").digest(s.toString().getBytes("UTF-8"));
|
|
||||||
final int c = ((b[0] & 0xFF) << 24) | ((b[1] & 0xFF) << 16)
|
|
||||||
| ((b[2] & 0xFF) << 8) | (b[3] & 0xFF);
|
|
||||||
// 143327882
|
|
||||||
System.out.println(c);
|
|
||||||
}
|
|
||||||
=end
|
|
||||||
actual = @history.string_to_code 'code@example.com'
|
|
||||||
assert_equal 143327882, actual
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -12,12 +12,13 @@ context "Precious::Views::LatestChanges" do
|
|||||||
setup do
|
setup do
|
||||||
@path = cloned_testpath("examples/lotr.git")
|
@path = cloned_testpath("examples/lotr.git")
|
||||||
@wiki = Gollum::Wiki.new(@path)
|
@wiki = Gollum::Wiki.new(@path)
|
||||||
|
@url = '/gollum/latest_changes'
|
||||||
Precious::App.set(:gollum_path, @path)
|
Precious::App.set(:gollum_path, @path)
|
||||||
Precious::App.set(:wiki_options, {:pagination_count => 10})
|
Precious::App.set(:wiki_options, {:pagination_count => 10})
|
||||||
end
|
end
|
||||||
|
|
||||||
test "displays_latest_changes" do
|
test "displays_latest_changes" do
|
||||||
get('/gollum/latest_changes')
|
get(@url)
|
||||||
body = last_response.body
|
body = last_response.body
|
||||||
|
|
||||||
assert body.include?("Charles Pence</span>"), "/latest_changes should include Author Charles Pence"
|
assert body.include?("Charles Pence</span>"), "/latest_changes should include Author Charles Pence"
|
||||||
@@ -27,6 +28,20 @@ context "Precious::Views::LatestChanges" do
|
|||||||
assert body.include?('<a href="Hobbit.md/874f597a5659b4c3b153674ea04e406ff393975e">Hobbit.md</a>'), "/latest_changes should include links to modified pages in #{body}"
|
assert body.include?('<a href="Hobbit.md/874f597a5659b4c3b153674ea04e406ff393975e">Hobbit.md</a>'), "/latest_changes should include links to modified pages in #{body}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test 'gravatar' do
|
||||||
|
Precious::App.set(:wiki_options, {:user_icons => 'gravatar'})
|
||||||
|
get @url
|
||||||
|
assert last_response.body.include?('<img src="https://secure.gravatar.com/'), "gravatar icon missing from #{@url}"
|
||||||
|
Precious::App.set(:wiki_options, {:user_icons => 'none'})
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'identicon' do
|
||||||
|
Precious::App.set(:wiki_options, {:user_icons => 'identicon'})
|
||||||
|
get @url
|
||||||
|
assert last_response.body.include?('class="identicon" data-identicon="'), "identicon icon missing from #{@url}"
|
||||||
|
Precious::App.set(:wiki_options, {:user_icons => 'none'})
|
||||||
|
end
|
||||||
|
|
||||||
test "extract destination file name in case of path renaming" do
|
test "extract destination file name in case of path renaming" do
|
||||||
view = Precious::Views::LatestChanges.new
|
view = Precious::Views::LatestChanges.new
|
||||||
assert_equal "newname.md", view.extract_renamed_path_destination("oldname.md => newname.md")
|
assert_equal "newname.md", view.extract_renamed_path_destination("oldname.md => newname.md")
|
||||||
@@ -36,4 +51,4 @@ context "Precious::Views::LatestChanges" do
|
|||||||
teardown do
|
teardown do
|
||||||
FileUtils.rm_rf(@path)
|
FileUtils.rm_rf(@path)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
Reference in New Issue
Block a user