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
|
||||
wiki_options[:display_metadata] = false
|
||||
end
|
||||
opts.on("--user-icons [MODE]", [:gravatar, :identicon, :none], "Use specific user-icons for history view.",
|
||||
"Can be set to 'gravatar', 'identicon' or 'none'. Default: 'none'.") do |mode|
|
||||
wiki_options[:user_icons] = mode
|
||||
opts.on("--user-icons [MODE]", [:gravatar, :identicon], "Use specific user-icons for history view.",
|
||||
"Can be set to 'gravatar' or 'identicon'. Default: standard avatar.") do |mode|
|
||||
wiki_options[:user_icons] = mode.to_s
|
||||
end
|
||||
opts.on("--template-dir [PATH]", "Specify custom mustache template directory.") do |path|
|
||||
wiki_options[:template_dir] = path
|
||||
|
||||
@@ -17,6 +17,7 @@ require 'gollum/views/helpers'
|
||||
require 'gollum/views/layout'
|
||||
require 'gollum/views/editable'
|
||||
require 'gollum/views/has_page'
|
||||
require 'gollum/views/has_user_icons'
|
||||
require 'gollum/views/pagination'
|
||||
|
||||
|
||||
@@ -402,6 +403,7 @@ module Precious
|
||||
@page = wikip.page
|
||||
@page_num = [params[:page_num].to_i, 1].max
|
||||
@max_count = settings.wiki_options.fetch(:pagination_count, 10)
|
||||
@wiki = @page.wiki
|
||||
unless @page.nil?
|
||||
@versions = @page.versions(
|
||||
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 identicon
|
||||
//= require mousetrap.min
|
||||
//= require gollum
|
||||
//= require gollum.dialog
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
// 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
|
||||
// Uses the route definitions in /lib/gollum/views/helpers.rb.
|
||||
// For example, routePath('delete') is equivalent to 'delete_path' in the mustache templates.
|
||||
@@ -498,20 +505,17 @@ $(document).ready(function() {
|
||||
});
|
||||
}
|
||||
|
||||
if( $('#wiki-history').length ){
|
||||
var lookup = {};
|
||||
if( $('#wiki-history').length || $('#page-history').length){
|
||||
var options = {
|
||||
format: 'svg',
|
||||
background: [255, 255, 255, 255] // rgba white
|
||||
};
|
||||
$('img.identicon').each(function(index, element){
|
||||
var $item = $(element);
|
||||
var code = parseInt($item.data('identicon'), 10);
|
||||
var img_bin = lookup[code];
|
||||
if( img_bin === undefined ){
|
||||
var size = 16;
|
||||
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);
|
||||
var item = $(element);
|
||||
var code = item.data('identicon');
|
||||
var img_bin = new Identicon(code, options).toString();
|
||||
img_bin = 'data:image/svg+xml;base64,' + 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 */
|
||||
|
||||
#user-icons {
|
||||
a, img, span, svg {
|
||||
vertical-align: middle;
|
||||
}
|
||||
img, svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.history #footer {
|
||||
margin-bottom: 7em;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
{{#versions}}
|
||||
<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="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-5">{{message}}</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/{{gravatar}}?s=16"
|
||||
alt="avatar: {{author}}" class="mini-gravatar"/>
|
||||
{{author}}
|
||||
</a>
|
||||
<img src="https://secure.gravatar.com/avatar/{{user_icon}}?s=20" class="mini-gravatar" onerror="brokenAvatarImage(this);" />
|
||||
<a href="https://gravatar.com/{{user_icon}}">{{author}}</a>
|
||||
@@ -1,5 +1,2 @@
|
||||
<a href="javascript:void(0)">
|
||||
<img src="{{#sprockets_image_path}}man_24.png{{/sprockets_image_path}}" alt="avatar: {{author}}"
|
||||
class="mini-gravatar identicon" data-identicon="{{identicon}}"/>
|
||||
{{author}}
|
||||
</a>
|
||||
<img src="" alt="avatar: {{author}}" class="identicon" data-identicon="{{user_icon}}" onerror="brokenAvatarImage(this);" />
|
||||
<span>{{author}}</span>
|
||||
@@ -1 +1,2 @@
|
||||
{{author}}
|
||||
{{#octicon}}person{{/octicon}}
|
||||
<span>{{author}}</span>
|
||||
@@ -11,7 +11,7 @@
|
||||
<div class="Box flex-auto">
|
||||
{{#versions}}
|
||||
<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-7">{{message}}<br/>
|
||||
{{#files}}
|
||||
|
||||
@@ -26,9 +26,6 @@
|
||||
|
||||
</script>
|
||||
{{#sprockets_javascript_tag}}app{{/sprockets_javascript_tag}}
|
||||
{{#use_identicon}}
|
||||
{{#sprockets_javascript_tag}}identicon_canvas{{/sprockets_javascript_tag}}
|
||||
{{/use_identicon}}
|
||||
{{#mathjax}}
|
||||
{{^mathjax_config}}
|
||||
<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
|
||||
include HasPage
|
||||
include Pagination
|
||||
include HasUserIcons
|
||||
include Sprockets::Helpers
|
||||
include Precious::Views::SprocketsHelpers
|
||||
|
||||
@@ -23,50 +24,12 @@ module Precious
|
||||
: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,
|
||||
:date => v.authored_date.strftime("%B %d, %Y"),
|
||||
:gravatar => Digest::MD5.hexdigest(v.author.email.strip.downcase),
|
||||
:identicon => self._identicon_code(v.author.email),
|
||||
:user_icon => self.user_icon_code(v.author.email),
|
||||
:date_full => v.authored_date,
|
||||
}
|
||||
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
|
||||
@editable
|
||||
end
|
||||
|
||||
@@ -2,6 +2,7 @@ module Precious
|
||||
module Views
|
||||
class LatestChanges < Layout
|
||||
include Pagination
|
||||
include HasUserIcons
|
||||
|
||||
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,
|
||||
:message => v.message.respond_to?(:force_encoding) ? v.message.force_encoding('UTF-8') : v.message,
|
||||
:date => v.authored_date.strftime("%B %d, %Y"),
|
||||
:gravatar => Digest::MD5.hexdigest(v.author.email.strip.downcase),
|
||||
:identicon => self._identicon_code(v.author.email),
|
||||
:user_icon => self.user_icon_code(v.author.email),
|
||||
:date_full => v.authored_date,
|
||||
:files => v.stats.files.map { |f,*rest|
|
||||
page_path = extract_renamed_path_destination(f)
|
||||
@@ -36,43 +36,6 @@ module Precious
|
||||
return file.gsub(/{.* => (.*)}/, '\1').gsub(/.* => (.*)/, '\1')
|
||||
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
|
||||
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.
|
||||
+4
-40
@@ -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/
|
||||
- group-folders.svg
|
||||
- group-files.svg
|
||||
- group-downloads.svg
|
||||
The identicon.js code is used under the BSD license.
|
||||
|
||||
lib/gollum/public/css/document.png
|
||||
lib/gollum/public/css/folder-horizontal.png
|
||||
lib/gollum/public/css/toggle-small-expand.png
|
||||
lib/gollum/public/css/toggle-small.png
|
||||
https://github.com/stewartlord/identicon.js/blob/master/identicon.js
|
||||
https://github.com/stewartlord/identicon.js/blob/master/README.md
|
||||
|
||||
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
|
||||
lib/gollum/public/gollum/javascript/identicon.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' });
|
||||
|
||||
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)
|
||||
|
||||
assert_match /#{expected}/, actual
|
||||
|
||||
@@ -7,19 +7,5 @@ context "Precious::Views::History" do
|
||||
@history = Precious::Views::History.new
|
||||
end
|
||||
|
||||
test "string_to_code" do
|
||||
# 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
|
||||
# No tests yet
|
||||
end
|
||||
|
||||
@@ -12,12 +12,13 @@ context "Precious::Views::LatestChanges" do
|
||||
setup do
|
||||
@path = cloned_testpath("examples/lotr.git")
|
||||
@wiki = Gollum::Wiki.new(@path)
|
||||
@url = '/gollum/latest_changes'
|
||||
Precious::App.set(:gollum_path, @path)
|
||||
Precious::App.set(:wiki_options, {:pagination_count => 10})
|
||||
end
|
||||
|
||||
test "displays_latest_changes" do
|
||||
get('/gollum/latest_changes')
|
||||
get(@url)
|
||||
body = last_response.body
|
||||
|
||||
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}"
|
||||
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
|
||||
view = Precious::Views::LatestChanges.new
|
||||
assert_equal "newname.md", view.extract_renamed_path_destination("oldname.md => newname.md")
|
||||
|
||||
Reference in New Issue
Block a user