From b774ee5cd0e79b703390f883e759cd85063561e2 Mon Sep 17 00:00:00 2001 From: Guillaume Grossetie Date: Wed, 17 Sep 2014 19:12:56 +0200 Subject: [PATCH 01/24] Use Asciidoctor 1.5.0 new syntax backtick Asciidoctor 1.5.0 is now using backtick for inline code. Replaces ASCIIDoc by AsciiDoc to respect the case. --- .../javascript/editor/langs/asciidoc.js | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/gollum/public/gollum/javascript/editor/langs/asciidoc.js b/lib/gollum/public/gollum/javascript/editor/langs/asciidoc.js index 31322c06..f8ee5cd6 100644 --- a/lib/gollum/public/gollum/javascript/editor/langs/asciidoc.js +++ b/lib/gollum/public/gollum/javascript/editor/langs/asciidoc.js @@ -1,11 +1,11 @@ /** - * ASCIIDoc Language Definition + * AsciiDoc Language Definition * */ (function($) { -var ASCIIDoc = { +var AsciiDoc = { 'function-bold' : { search: /(^[\n]+)([\n\s]*)/g, @@ -19,7 +19,7 @@ var ASCIIDoc = { 'function-code' : { search: /(^[\n]+)([\n\s]*)/g, - replace: "+$1+$2" + replace: "`$1`$2" }, 'function-ul' : { @@ -102,20 +102,20 @@ var ASCIIDoc = { }; -$.GollumEditor.defineLanguage('asciidoc', ASCIIDoc); +$.GollumEditor.defineLanguage('asciidoc', AsciiDoc); -var ASCIIDocHelp = [ +var AsciiDocHelp = [ { menuName: 'Text Formatting', content: [ { menuName: 'Headers', - data: '

ASCIIDoc headers can be written in two ways: with differing underlines or with different indentation using = (equals sign). ASCIIDoc supports headings 1-4. The editor will automatically use the = notation. To create a level one header, prefix your line with one =. Level two headers are created with == and so on.

' + data: '

AsciiDoc headers can be written in two ways: with differing underlines or with different indentation using = (equals sign). AsciiDoc supports headings 1-4. The editor will automatically use the = notation. To create a level one header, prefix your line with one =. Level two headers are created with == and so on.

' }, { menuName: 'Bold / Italic', - data: '

To display text as bold, wrap the text in * (asterisks). To display text as italic, wrap the text in _ (underscores). To create monospace text, wrap the text in + (plus signs).' + data: '

To display text as bold, wrap the text in * (asterisks). To display text as italic, wrap the text in _ (underscores). To create monospace text, wrap the text in ` (backtick).' }, { menuName: 'Scripts', @@ -123,7 +123,7 @@ var ASCIIDocHelp = [ }, { menuName: 'Special Characters', - data: '

ASCIIDoc will automatically convert textual representations of commonly-used special characters. For example, (R) becomes ®, (C) becomes © and (TM) becomes ™.

' + data: '

AsciiDoc will automatically convert textual representations of commonly-used special characters. For example, (R) becomes ®, (C) becomes © and (TM) becomes ™.

' } ] }, @@ -132,7 +132,7 @@ var ASCIIDocHelp = [ content: [ { menuName: 'Paragraphs', - data: '

ASCIIDoc allows paragraphs to have optional titles or icons to denote special sections. To make a normal paragraph, simply add a line between blocks and a new paragraph will start. If you want to title your paragraphs, adda line prefixed by . (full stop). An example paragraph with optional title is displayed below:

.Optional Title

This is my paragraph. It is two sentences long.

' + data: '

AsciiDoc allows paragraphs to have optional titles or icons to denote special sections. To make a normal paragraph, simply add a line between blocks and a new paragraph will start. If you want to title your paragraphs, adda line prefixed by . (full stop). An example paragraph with optional title is displayed below:

.Optional Title

This is my paragraph. It is two sentences long.

' }, { menuName: 'Source Blocks', @@ -157,12 +157,12 @@ var ASCIIDocHelp = [ }, { menuName: 'Images', - data: '

Images in ASCIIDoc work much like hyperlinks, but image URLs are prefixed with image:. For example, to link to an image at images/icons/home.png, write image:images/icons/home.png. Alt text can be added by appending the text to the URI in [ (brackets).

' + data: '

Images in AsciiDoc work much like hyperlinks, but image URLs are prefixed with image:. For example, to link to an image at images/icons/home.png, write image:images/icons/home.png. Alt text can be added by appending the text to the URI in [ (brackets).

' } ] } ]; -$.GollumEditor.defineHelp('asciidoc', ASCIIDocHelp); +$.GollumEditor.defineHelp('asciidoc', AsciiDocHelp); })(jQuery); From 846642583643ccc585f9bcbc40c7ff6550659f94 Mon Sep 17 00:00:00 2001 From: Guillaume Grossetie Date: Thu, 18 Sep 2014 20:03:35 +0200 Subject: [PATCH 02/24] Adds headers to the AsciiDoc editor --- .../gollum/javascript/editor/langs/asciidoc.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/lib/gollum/public/gollum/javascript/editor/langs/asciidoc.js b/lib/gollum/public/gollum/javascript/editor/langs/asciidoc.js index 31322c06..3901e44b 100644 --- a/lib/gollum/public/gollum/javascript/editor/langs/asciidoc.js +++ b/lib/gollum/public/gollum/javascript/editor/langs/asciidoc.js @@ -37,6 +37,21 @@ var ASCIIDoc = { replace: "----\n$1$2\n----\n" }, + 'function-h1' : { + search: /(.+)([\n]?)/g, + replace: "= $1$2" + }, + + 'function-h2' : { + search: /(.+)([\n]?)/g, + replace: "== $1$2" + }, + + 'function-h3' : { + search: /(.+)([\n]?)/g, + replace: "=== $1$2" + }, + 'function-link' : { exec: function( txt, selText, $field ) { var results = null; From 1148d29439a163c031c78926597771aa3e218ceb Mon Sep 17 00:00:00 2001 From: Geoffrey Roberts Date: Thu, 29 May 2014 16:31:10 +1000 Subject: [PATCH 03/24] Made the Gollum theme responsive. Not a particularly comprehensive change in style, just one that removes all the fixed sizing for browsers below 940px in width. Closes #831. --- HISTORY.md | 5 + lib/gollum/public/gollum/css/dialog.css | 132 +++++++-- lib/gollum/public/gollum/css/editor.css | 253 +++++++++++++----- lib/gollum/public/gollum/css/gollum.css | 155 +++++++++-- lib/gollum/public/gollum/css/ie7.css | 6 + lib/gollum/public/gollum/css/template.css | 9 +- .../public/gollum/javascript/gollum.dialog.js | 30 ++- lib/gollum/templates/editor.mustache | 2 +- lib/gollum/templates/layout.mustache | 3 + 9 files changed, 491 insertions(+), 104 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index d2b59459..d6fd9ec8 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,3 +1,8 @@ +# Next release candidate + +* Major enhancements + * Made the Gollum theme responsive [rtrvrtg] (#831) + # 2.4.11 / 2013-01-08 * Numerous security issues have been fixed. Please update to `2.4.11` diff --git a/lib/gollum/public/gollum/css/dialog.css b/lib/gollum/public/gollum/css/dialog.css index dfbd7938..8cfca2aa 100755 --- a/lib/gollum/public/gollum/css/dialog.css +++ b/lib/gollum/public/gollum/css/dialog.css @@ -4,8 +4,11 @@ display: block; overflow: visible; position: absolute; - top: 50%; - left: 50%; + top: 0; + left: 0; + z-index: 999999; + width: 100%; + height: 100%; } #gollum-dialog-dialog.active { @@ -13,24 +16,117 @@ } #gollum-dialog-dialog-inner { - margin: 0 0 0 -225px; - position: relative; - width: 450px; - - border: 7px solid #999; - border: 7px solid rgba(0, 0, 0, 0.3); - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; + margin: 0px; + top: 0px; + right: 0px; + bottom: 0px; + left: 0px; + width: 100%; + height: 100%; } #gollum-dialog-dialog-bg { background-color: #fff; - overflow: hidden; padding: 1em; - background: -webkit-gradient(linear, left top, left bottom, from(#f7f7f7), to(#ffffff)); - background: -moz-linear-gradient(top, #f7f7f7, #ffffff); + height: 100%; + box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; +} + +@media all and (min-width: 480px) { + #gollum-dialog-dialog { + display: block; + overflow: visible; + position: absolute; + position: fixed; + top: 0; + left: 0; + z-index: 999999; + width: auto; + height: auto; + } + + #gollum-dialog-dialog.active { + display: block; + } + + #gollum-dialog-dialog-inner { + margin: auto; + position: fixed; + + width: auto; + height: auto; + + min-width: 280px; + min-height: 380px; + + max-width: 450px; + max-height: 450px; + + top: 10px; + right: 10px; + bottom: 10px; + left: 10px; + + border: 7px solid #999; + border: 7px solid rgba(0, 0, 0, 0.3); + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + } + + #gollum-dialog-dialog-bg { + background-color: #fff; + overflow: hidden; + padding: 1em; + + background: -webkit-gradient(linear, left top, left bottom, from(#f7f7f7), to(#ffffff)); + background: -moz-linear-gradient(top, #f7f7f7, #ffffff); + + height: 100%; + box-sizing: border-box; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + } +} + +@media all and (min-width: 940px) { + #gollum-dialog-dialog { + position: absolute; + top: 50%; + left: 50%; + width: auto; + height: auto; + } + + #gollum-dialog-dialog-inner { + margin: 0 0 0 -225px; + position: relative; + + width: 450px; + height: auto; + + top: auto; + right: auto; + bottom: auto; + left: auto; + + border: 7px solid #999; + border: 7px solid rgba(0, 0, 0, 0.3); + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + } + + #gollum-dialog-dialog-bg { + height: auto; + + box-sizing: content-box; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + } } #gollum-dialog-dialog-inner h4 { @@ -52,10 +148,16 @@ display: block; border: 0; margin: 0; - overflow: hidden; padding: 0; } +#gollum-dialog-dialog-body fieldset:after { + content: "."; + display: block; + clear: both; + visibility: hidden; +} + #gollum-dialog-dialog-body fieldset .field { margin: 0 0 1.5em 0; padding: 0; diff --git a/lib/gollum/public/gollum/css/editor.css b/lib/gollum/public/gollum/css/editor.css index d743778d..8e1992fb 100755 --- a/lib/gollum/public/gollum/css/editor.css +++ b/lib/gollum/public/gollum/css/editor.css @@ -19,15 +19,15 @@ a { } #gollum-editor { - border: 1px solid #e4e4e4; - background: #f9f9f9; - margin: 1em 0 5em; - overflow: hidden; - padding: 1em 1em 0.4em; + margin: 0 0 5em; + padding: 0em 1em 0.4em; +} - border-radius: 1em; - -moz-border-radius: 1em; - -webkit-border-radius: 1em; +#gollum-editor:after { + content: "."; + display: block; + visibility: hidden; + clear: both; } .ff #gollum-editor, @@ -35,6 +35,18 @@ a { padding-bottom: 1em; } +@media all and (min-width: 940px) { + #gollum-editor { + border: 1px solid #e4e4e4; + background: #f9f9f9; + margin: 1em 0 5em; + + border-radius: 1em; + -moz-border-radius: 1em; + -webkit-border-radius: 1em; + } +} + #gollum-editor form fieldset { border: 0; margin: 0; @@ -45,7 +57,13 @@ a { #gollum-editor .singleline { display: block; margin: 0 0 0.7em 0; - overflow: hidden; +} + +#gollum-editor .singleline:after { + content: "."; + display: block; + visibility: hidden; + clear: both; } #gollum-editor .singleline input { @@ -94,7 +112,6 @@ a { /* @control function-bar */ #gollum-editor #gollum-editor-function-bar { border-bottom: 1px solid #ddd; - overflow: hidden; padding: 0; } @@ -109,9 +126,21 @@ a { #gollum-editor #gollum-editor-function-bar.active #gollum-editor-function-buttons { display: block; - float: left; - overflow: hidden; - padding: 0 0 1.1em 0; + margin: 0; + padding: 0; +} + +@media all and (min-width: 940px) { + #gollum-editor #gollum-editor-function-bar { + overflow: hidden; + } + + #gollum-editor #gollum-editor-function-bar.active #gollum-editor-function-buttons { + overflow: hidden; + margin: 0; + padding: 0 0 1.1em 0; + float: left; + } } #gollum-editor #gollum-editor-function-bar a.function-button { @@ -120,12 +149,12 @@ a { color: #333; display: block; float: left; - height: 25px; + height: 32px; overflow: hidden; - margin: 0.2em 0.5em 0 0; + margin: 1px 1px 0 0; /* text-indent: -5000px; */ text-shadow: 0 1px 0 #fff; - width: 25px; + width: 32px; border-radius: 0.3em; -moz-border-radius: 0.3em; @@ -150,41 +179,84 @@ a { background-image: url(../images/icon-sprite.png); background-repeat: no-repeat; display: block; - height: 25px; + height: 32px; overflow: hidden; text-indent: -5000px; - width: 25px; + width: 32px; } -a#function-bold span { background-position: 0 0; } -a#function-italic span { background-position: -27px 0; } -a#function-underline span { background-position: -54px 0; } -a#function-code span { background-position: -82px 0; } -a#function-ul span { background-position: -109px 0; } -a#function-ol span { background-position: -136px 0; } -a#function-blockquote span { background-position: -163px 0; } -a#function-hr span { background-position: -190px 0; } -a#function-h1 span { background-position: -217px 0; } -a#function-h2 span { background-position: -244px 0; } -a#function-h3 span { background-position: -271px 0; } -a#function-link span { background-position: -298px 0; } -a#function-image span { background-position: -324px 0; } -a#function-help span { background-position: -405px 0; } +a#function-bold span { background-position: 3px 3px; } +a#function-italic span { background-position: -24px 3px; } +a#function-underline span { background-position: -51px 3px; } +a#function-code span { background-position: -79px 3px; } +a#function-ul span { background-position: -106px 3px; } +a#function-ol span { background-position: -133px 3px; } +a#function-blockquote span { background-position: -160px 3px; } +a#function-hr span { background-position: -187px 3px; } +a#function-h1 span { background-position: -214px 3px; } +a#function-h2 span { background-position: -241px 3px; } +a#function-h3 span { background-position: -268px 3px; } +a#function-link span { background-position: -295px 3px; } +a#function-image span { background-position: -321px 3px; } +a#function-help span { background-position: -402px 3px; } -a#function-bold:hover span { background-position: 0 -28px; } -a#function-italic:hover span { background-position: -27px -28px; } -a#function-underline:hover span { background-position: -54px -28px; } -a#function-code:hover span { background-position: -82px -28px; } -a#function-ul:hover span { background-position: -109px -28px; } -a#function-ol:hover span { background-position: -136px -28px; } -a#function-blockquote:hover span { background-position: -163px -28px; } -a#function-hr:hover span { background-position: -190px -28px; } -a#function-h1:hover span { background-position: -217px -28px; } -a#function-h2:hover span { background-position: -244px -28px; } -a#function-h3:hover span { background-position: -271px -28px; } -a#function-link:hover span { background-position: -298px -28px; } -a#function-image:hover span { background-position: -324px -28px; } -a#function-help:hover span { background-position: -405px -28px; } +a#function-bold:hover span { background-position: 3px -25px; } +a#function-italic:hover span { background-position: -24px -25px; } +a#function-underline:hover span { background-position: -51px -25px; } +a#function-code:hover span { background-position: -79px -25px; } +a#function-ul:hover span { background-position: -106px -25px; } +a#function-ol:hover span { background-position: -133px -25px; } +a#function-blockquote:hover span { background-position: -160px -25px; } +a#function-hr:hover span { background-position: -187px -25px; } +a#function-h1:hover span { background-position: -214px -25px; } +a#function-h2:hover span { background-position: -241px -25px; } +a#function-h3:hover span { background-position: -268px -25px; } +a#function-link:hover span { background-position: -295px -25px; } +a#function-image:hover span { background-position: -321px -25px; } +a#function-help:hover span { background-position: -402px -25px; } + +@media all and (min-width: 940px) { + #gollum-editor #gollum-editor-function-bar a.function-button { + height: 25px; + width: 25px; + margin: 0.2em 0.5em 0 0; + } + + #gollum-editor #gollum-editor-function-bar a span { + width: 25px; + height: 25px; + } + + a#function-bold span { background-position: 0 0; } + a#function-italic span { background-position: -27px 0; } + a#function-underline span { background-position: -54px 0; } + a#function-code span { background-position: -82px 0; } + a#function-ul span { background-position: -109px 0; } + a#function-ol span { background-position: -136px 0; } + a#function-blockquote span { background-position: -163px 0; } + a#function-hr span { background-position: -190px 0; } + a#function-h1 span { background-position: -217px 0; } + a#function-h2 span { background-position: -244px 0; } + a#function-h3 span { background-position: -271px 0; } + a#function-link span { background-position: -298px 0; } + a#function-image span { background-position: -324px 0; } + a#function-help span { background-position: -405px 0; } + + a#function-bold:hover span { background-position: 0 -28px; } + a#function-italic:hover span { background-position: -27px -28px; } + a#function-underline:hover span { background-position: -54px -28px; } + a#function-code:hover span { background-position: -82px -28px; } + a#function-ul:hover span { background-position: -109px -28px; } + a#function-ol:hover span { background-position: -136px -28px; } + a#function-blockquote:hover span { background-position: -163px -28px; } + a#function-hr:hover span { background-position: -190px -28px; } + a#function-h1:hover span { background-position: -217px -28px; } + a#function-h2:hover span { background-position: -244px -28px; } + a#function-h3:hover span { background-position: -271px -28px; } + a#function-link:hover span { background-position: -298px -28px; } + a#function-image:hover span { background-position: -324px -28px; } + a#function-help:hover span { background-position: -405px -28px; } +} #gollum-editor #gollum-editor-function-bar a.disabled { @@ -192,14 +264,19 @@ a#function-help:hover span { background-position: -405px -28px; } } #gollum-editor #gollum-editor-function-bar span.function-divider { - display: block; - float: left; - width: 0.5em; + display: none; } #gollum-editor #gollum-editor-function-bar #gollum-editor-format-selector { - overflow: hidden; - padding: .2em 0 .5em 0; + padding: 0.2em 0 0.5em 0; + clear: both; +} + +#gollum-editor #gollum-editor-function-bar #gollum-editor-format-selector:after { + content: "."; + display: block; + clear: both; + visibility: hidden; } #gollum-editor #gollum-editor-function-bar @@ -208,13 +285,12 @@ a#function-help:hover span { background-position: -405px -28px; } border: 1px solid #ddd; color: #333; - float: right; font-size: 1em; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-weight: bold; line-height: 1.6em; padding: 0.3em 0.4em; - + display: inline-block; border-radius: 0.5em; -moz-border-radius: 0.5em; @@ -224,11 +300,11 @@ a#function-help:hover span { background-position: -405px -28px; } #gollum-editor #gollum-editor-function-bar #gollum-editor-format-selector label { color: #999; - float: right; font-size: 1em; font-weight: bold; line-height: 1.6em; padding: .3em 0.5em 0 0; + display: inline-block; } #gollum-editor #gollum-editor-function-bar @@ -236,6 +312,31 @@ a#function-help:hover span { background-position: -405px -28px; } content: ':'; } +@media all and (min-width: 940px) { + #gollum-editor #gollum-editor-function-bar span.function-divider { + display: block; + width: 0.5em; + } + + #gollum-editor #gollum-editor-function-bar span.function-divider { + float: left; + } + + #gollum-editor #gollum-editor-function-bar + #gollum-editor-format-selector { + clear: none; + text-align: right; + } + + #gollum-editor #gollum-editor-function-bar + #gollum-editor-format-selector select { + } + + #gollum-editor #gollum-editor-function-bar + #gollum-editor-format-selector label { + } +} + /* @section form-fields */ @@ -245,12 +346,18 @@ a#function-help:hover span { background-position: -405px -28px; } font-size: 1em; font-family: Consolas, "Liberation Mono", Courier, monospace; line-height: 1.4em; - margin: 1em 0 0.4em; + margin: 0 0 0.4em; padding: 0.5em; width: 98%; height: 20em; } +@media all and (min-width: 940px) { + #gollum-editor textarea { + margin: 1em 0 0.4em; + } +} + #gollum-editor input#gollum-editor-submit { background-color: #f7f7f7; border: 1px solid #d4d4d4; @@ -445,6 +552,7 @@ a#function-help:hover span { background-position: -405px -28px; } /* @section help */ #gollum-editor-help { + clear: both; margin: 0; overflow: hidden; padding: 0; @@ -455,13 +563,13 @@ a#function-help:hover span { background-position: -405px -28px; } #gollum-editor-help-parent, #gollum-editor-help-list { display: block; - float: left; - height: 17em; list-style-type: none; - overflow: auto; margin: 0; - padding: 1em 0; - width: 18%; + float: left; + width: 50%; + box-sizing: border-box; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; } #gollum-editor-help-parent { @@ -491,6 +599,7 @@ a#function-help:hover span { background-position: -405px -28px; } width: auto; padding: 0.2em 1em; text-shadow: 0 -1px 0 #fff; + font-size: 0.8em; } #gollum-editor-help-parent li a:hover, @@ -518,6 +627,7 @@ a#function-help:hover span { background-position: -405px -28px; } overflow: auto; height: 17em; padding: 1em; + clear: both; } #gollum-editor-help-content { @@ -532,6 +642,29 @@ a#function-help:hover span { background-position: -405px -28px; } padding: 0; } + @media all and (min-width: 940px) { + #gollum-editor-help { + clear: none; + } + + #gollum-editor-help-parent, + #gollum-editor-help-list { + height: 17em; + width: 18%; + overflow: auto; + padding: 1em 0; + } + + #gollum-editor-help-parent li a, + #gollum-editor-help-list li a { + font-size: 1em; + } + + #gollum-editor-help-wrapper { + clear: none; + } + } + /* IE */ .ie #gollum-editor .singleline input { padding-top: 0.25em; diff --git a/lib/gollum/public/gollum/css/gollum.css b/lib/gollum/public/gollum/css/gollum.css index 4b582fec..a3ca3f35 100755 --- a/lib/gollum/public/gollum/css/gollum.css +++ b/lib/gollum/public/gollum/css/gollum.css @@ -21,9 +21,15 @@ body, html { #wiki-wrapper { margin: 0 auto; overflow: visible; - width: 920px; - padding-left:20px; - padding-right:20px; + width: 100%; +} + +@media all and (min-width: 940px) { + #wiki-wrapper { + max-width: 920px; + padding-left:20px; + padding-right:20px; + } } a:link { @@ -39,22 +45,41 @@ a:hover, a:visited { /* @section head */ #head { - border-bottom: 1px solid #ddd; - margin: 4em 0 1.5em; - padding-bottom: 0.3em; + margin: 1em 0 0; + padding: 0; overflow: hidden; } #head h1 { - font-size: 2.5em; + font-size: 1.5em; float: left; line-height: normal; margin: 0; - padding: 2px 0 0 0; + padding: 0 0 0 0.667em; } #head ul.actions { - float: right; + clear: both; + margin: 0 1em; +} + +@media all and (min-width: 940px) { + #head { + border-bottom: 1px solid #ddd; + padding-bottom: 0.3em; + margin: 4em 0 1.5em; + } + + #head h1 { + font-size: 2.5em; + padding: 2px 0 0 0; + } + + #head ul.actions { + clear: none; + float: right; + margin: 0; + } } /* @section content */ @@ -244,6 +269,16 @@ a:hover, a:visited { font-weight: bold; } +#footer .actions { + margin-left: 1em; +} + +@media all and (min-width: 940px) { + #footer .actions { + margin: 0; + } +} + /* @section history */ .history h1 { @@ -257,7 +292,7 @@ a:hover, a:visited { } #wiki-history { - margin-top: 2em; + margin: 2em 1em 0 1em; } #wiki-history fieldset { @@ -283,7 +318,8 @@ a:hover, a:visited { } #wiki-history table tr td { - border: 1px solid #c0dce9; + border-top: 1px solid #c0dce9; + border-bottom: 1px solid #c0dce9; font-size: 1em; line-height: 1.6em; margin: 0; @@ -291,8 +327,8 @@ a:hover, a:visited { } #wiki-history table tr td.checkbox { - width: 4em; - padding: 0.3em; + width: auto; + padding: 0 0.2em 0 0; } #wiki-history table tr td.checkbox input { @@ -364,6 +400,25 @@ a:hover, a:visited { margin: 0 0.6em 0 0; } +@media all and (min-width: 940px) { + #wiki-history { + margin: 2em 0 0 0; + } + + #wiki-history table tr td { + border: 1px solid #c0dce9; + font-size: 1em; + line-height: 1.6em; + margin: 0; + padding: 0.3em 0.7em; + } + + #wiki-history table tr td.checkbox { + width: 4em; + padding: 0.3em; + } +} + /* @section edit */ .edit h1 { @@ -378,6 +433,7 @@ a:hover, a:visited { /* @section search */ + .results h1 { color: #999; font-weight: normal; @@ -390,6 +446,8 @@ a:hover, a:visited { .results #results { border-bottom: 1px solid #ccc; + margin-left: 1em; + margin-right: 1em; margin-bottom: 2em; padding-bottom: 2em; } @@ -400,12 +458,33 @@ a:hover, a:visited { } .results #results ul li { - font-size: 1.2em; - line-height: 1.6em; - list-style-position: outside; + list-style: none; padding: 0.2em 0; } +.results #results ul li a { + word-wrap: break-word; +} + +@media all and (min-width: 640px) { + .results #results ul li { + font-size: 1.2em; + } +} + +@media all and (min-width: 940px) { + .results #results { + margin-left: 0; + margin-right: 0; + } + + .results #results ul li { + list-style: disc; + list-style-position: outside; + line-height: 1.6em; + } +} + .results #results ul li span.count { color: #999; } @@ -522,8 +601,8 @@ ul.actions { ul.actions li { float: left; font-size: 0.9em; - margin-left: 0.6em; - margin-bottom: 0.6em; + margin-left: 1px; + margin-bottom: 1px; } .minibutton a { @@ -533,7 +612,7 @@ ul.actions { display: block; font-weight: bold; margin: 0; - padding: 0.4em 1em; + padding: 0.6em 1em; height: 1.4em; text-shadow: 0 1px 0 #fff; @@ -547,6 +626,18 @@ ul.actions { -webkit-border-radius: 3px; } +@media all and (min-width: 940px) { + ul.actions li { + margin-left: 0.6em; + margin-bottom: 0.6em; + } + + .minibutton a { + padding: 0.4em 1em; + height: 1.4em; + } +} + #search-submit { background-color: #f7f7f7; border: 1px solid #d4d4d4; @@ -627,7 +718,7 @@ ul.actions { /* @control searchbar */ #head #searchbar { float: right; - padding: 0; + padding: 2px 0 0 0; overflow: hidden; } @@ -684,7 +775,7 @@ ul.actions { height: inherit; overflow: hidden; text-indent: -5000px; - width: 28px; + width: 32px; } .ff #head #searchbar #searchbar-fauxtext #search-submit span, @@ -697,11 +788,31 @@ ul.actions { padding: 0; } +@media all and (min-width: 940px) { + #head #searchbar { + padding: 0; + } + + #head #searchbar #searchbar-fauxtext #search-submit span { + width: 28px; + } + + #head #searchbar #searchbar-fauxtext #search-submit:hover span { + background-position: -431px -28px; + } +} + /* @section pages */ #pages { font-size: 1.2em; - margin-bottom: 20px; + margin: 0 1em 20px 1em; +} + +@media all and (min-width: 940px) { + #pages { + margin: 0 0 20px 0; + } } #pages ul { diff --git a/lib/gollum/public/gollum/css/ie7.css b/lib/gollum/public/gollum/css/ie7.css index 31bf7e49..112d33a2 100755 --- a/lib/gollum/public/gollum/css/ie7.css +++ b/lib/gollum/public/gollum/css/ie7.css @@ -1,5 +1,11 @@ /* IE7-specific styles */ +.ie #wiki-wrapper { + width: 920px; + padding-left:20px; + padding-right:20px; +} + .ie #head #searchbar #searchbar-fauxtext input#search-query { border: 0; float: left; diff --git a/lib/gollum/public/gollum/css/template.css b/lib/gollum/public/gollum/css/template.css index cfd6f478..d950f89e 100644 --- a/lib/gollum/public/gollum/css/template.css +++ b/lib/gollum/public/gollum/css/template.css @@ -52,7 +52,6 @@ body { font: 13.34px Helvetica, arial, freesans, clean, sans-serif; font-size: small; line-height: 1.4; - min-width: 980px; } img { @@ -86,13 +85,19 @@ a:active, a:hover { } .markdown-body { - padding: 30px; + padding: 1em; font-size: 15px; line-height: 1.7; overflow: hidden; word-wrap: break-word; } +@media all and (min-width: 940px) { + .markdown-body { + padding: 30px; + } +} + .markdown-body > *:first-child { margin-top: 0 !important; } diff --git a/lib/gollum/public/gollum/javascript/gollum.dialog.js b/lib/gollum/public/gollum/javascript/gollum.dialog.js index 0bf0e0a4..112a59a5 100755 --- a/lib/gollum/public/gollum/javascript/gollum.dialog.js +++ b/lib/gollum/public/gollum/javascript/gollum.dialog.js @@ -13,6 +13,12 @@ markupCreated: false, markup: '', + currentAspect: function(){ + if (window.innerWidth < 480) return "small-mobile"; + if ($('#gollum-dialog-dialog').css('position') == 'fixed') return "large-mobile"; + return "desktop"; + }, + attachEvents: function( evtOK ) { $('#gollum-dialog-action-ok').click(function( e ) { Dialog.eventOK( e, evtOK ); @@ -185,6 +191,8 @@ } }); } + + $(window).unbind('resize', Dialog.resize); } }, @@ -268,14 +276,28 @@ }); } } + + $(window).bind('resize', Dialog.resize); } }, + resize: function(){ + Dialog.position(); + }, + position: function() { - var dialogHeight = $('#gollum-dialog-dialog-inner').height(); - $('#gollum-dialog-dialog-inner') - .css('height', dialogHeight + 'px') - .css('margin-top', -1 * parseInt( dialogHeight / 2 )); + if (Dialog.currentAspect() == "small-mobile") { + $('#gollum-dialog-dialog-inner').css('height', '100%').css('margin-top', 'auto'); + } + else if (Dialog.currentAspect() == "large-mobile") { + $('#gollum-dialog-dialog-inner').css('height', 'auto').css('margin-top', 'auto'); + } + else if (Dialog.currentAspect() == "desktop") { + var dialogHeight = $('#gollum-dialog-dialog-inner').height(); + $('#gollum-dialog-dialog-inner') + .css('height', dialogHeight + 'px') + .css('margin-top', -1 * parseInt( dialogHeight / 2 )); + } } }; diff --git a/lib/gollum/templates/editor.mustache b/lib/gollum/templates/editor.mustache index 46cbaf4f..562b415d 100644 --- a/lib/gollum/templates/editor.mustache +++ b/lib/gollum/templates/editor.mustache @@ -55,6 +55,7 @@
+ -
diff --git a/lib/gollum/templates/layout.mustache b/lib/gollum/templates/layout.mustache index 7c58bdd4..357d107b 100644 --- a/lib/gollum/templates/layout.mustache +++ b/lib/gollum/templates/layout.mustache @@ -2,6 +2,9 @@ + + + From e05f523145952c4a7b7a1179b2b45df7eb72f4cb Mon Sep 17 00:00:00 2001 From: Guillaume Grossetie Date: Sat, 4 Oct 2014 12:37:21 +0200 Subject: [PATCH 04/24] Horizontal scroll when table is too wide --- lib/gollum/public/gollum/css/gollum.css | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/gollum/public/gollum/css/gollum.css b/lib/gollum/public/gollum/css/gollum.css index a3ca3f35..cd577b78 100755 --- a/lib/gollum/public/gollum/css/gollum.css +++ b/lib/gollum/public/gollum/css/gollum.css @@ -114,6 +114,12 @@ a:hover, a:visited { width: 100%; } +#wiki-body table { + display: block; + overflow: auto; + border: 0; +} + .has-sidebar #wiki-body { width: 68%; } From 2664fdca30ff00c924d8b9c84b8cdaf0290353e1 Mon Sep 17 00:00:00 2001 From: Guillaume Grossetie Date: Sat, 4 Oct 2014 12:45:35 +0200 Subject: [PATCH 05/24] Fix css selector for Asciidoctor h1 html ouptput --- lib/gollum/views/page.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/gollum/views/page.rb b/lib/gollum/views/page.rb index 5c20d59a..dd99d1a0 100644 --- a/lib/gollum/views/page.rb +++ b/lib/gollum/views/page.rb @@ -138,7 +138,7 @@ module Precious def find_header_node(doc) case @page.format when :asciidoc - doc.css("div#gollum-root > div#header > h1:first-child") + doc.css("div#gollum-root > h1:first-child") when :org doc.css("div#gollum-root > p.title:first-child") when :pod From 16dd7e46efb90cf27aedefba203626927f148acf Mon Sep 17 00:00:00 2001 From: Lucas Clemente Date: Wed, 5 Feb 2014 12:44:53 +0100 Subject: [PATCH 06/24] allow uploading files by drag and drop --- lib/gollum/app.rb | 16 ++++-- lib/gollum/public/gollum/css/editor.css | 25 ++++++++ lib/gollum/public/gollum/css/template.css | 45 +++++++++++++++ .../gollum/javascript/editor/gollum.editor.js | 57 +++++++++++++++++++ lib/gollum/templates/editor.mustache | 6 +- lib/gollum/templates/layout.mustache | 2 +- lib/gollum/views/create.rb | 8 +++ lib/gollum/views/edit.rb | 8 +++ 8 files changed, 161 insertions(+), 6 deletions(-) diff --git a/lib/gollum/app.rb b/lib/gollum/app.rb index 600ec654..beb1448f 100644 --- a/lib/gollum/app.rb +++ b/lib/gollum/app.rb @@ -129,8 +129,10 @@ module Precious wikip = wiki_page(params[:splat].first) @name = wikip.name @path = wikip.path + @upload_dest = find_upload_dest(@path) wiki = wikip.wiki + @allow_uploads = wiki.allow_uploads if page = wikip.page if wiki.live_preview && page.format.to_s.include?('markdown') && supported_useragent?(request.user_agent) live_preview_url = '/livepreview/index.html?page=' + encodeURIComponent(@name) @@ -266,6 +268,8 @@ module Precious wikip = wiki_page(params[:splat].first.gsub('+', '-')) @name = wikip.name.to_url @path = wikip.path + @allow_uploads = wikip.wiki.allow_uploads + @upload_dest = find_upload_dest(@path) page_dir = settings.wiki_options[:page_file_dir].to_s unless page_dir.empty? @@ -453,10 +457,7 @@ module Precious @page = page @name = name @content = page.formatted_data - @upload_dest = settings.wiki_options[:allow_uploads] ? - (settings.wiki_options[:per_page_uploads] ? - "#{path}/#{@name}".sub(/^\/\//, '') : 'uploads' - ) : '' + @upload_dest = find_upload_dest(path) # Extensions and layout data @editable = true @@ -505,5 +506,12 @@ module Precious commit_message.merge! author_parameters unless author_parameters.nil? commit_message end + + def find_upload_dest(path) + settings.wiki_options[:allow_uploads] ? + (settings.wiki_options[:per_page_uploads] ? + "#{path}/#{@name}".sub(/^\/\//, '') : 'uploads' + ) : '' + end end end diff --git a/lib/gollum/public/gollum/css/editor.css b/lib/gollum/public/gollum/css/editor.css index 8e1992fb..73a0915e 100755 --- a/lib/gollum/public/gollum/css/editor.css +++ b/lib/gollum/public/gollum/css/editor.css @@ -338,6 +338,31 @@ a#function-help:hover span { background-position: -402px -25px; } } +/* @section uploads */ + +#gollum-editor-body.dragging { + box-shadow: 0 0 10px #AAE000; +} + +#gollum-editor-body.uploading { + opacity: 0.5; +} + +#gollum-editor-body + div { + display: none; + font-size: 1.5em; +} + +#gollum-editor-body + div > i { + font-size: 1em; +} + +#gollum-editor-body.uploading + div { + display: block; +} + + + /* @section form-fields */ #gollum-editor textarea { diff --git a/lib/gollum/public/gollum/css/template.css b/lib/gollum/public/gollum/css/template.css index d950f89e..6bde233e 100644 --- a/lib/gollum/public/gollum/css/template.css +++ b/lib/gollum/public/gollum/css/template.css @@ -27,6 +27,51 @@ content: "\f0c1"; } +.fa-spinner:before { + content: "\f110"; +} + +.fa-spin { + -webkit-animation: spin 2s infinite linear; + -moz-animation: spin 2s infinite linear; + -o-animation: spin 2s infinite linear; + animation: spin 2s infinite linear; +} +@-moz-keyframes spin { + 0% { + -moz-transform: rotate(0deg); + } + 100% { + -moz-transform: rotate(359deg); + } +} +@-webkit-keyframes spin { + 0% { + -webkit-transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + } +} +@-o-keyframes spin { + 0% { + -o-transform: rotate(0deg); + } + 100% { + -o-transform: rotate(359deg); + } +} +@keyframes spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} + /* margin & padding reset*/ * { margin: 0; diff --git a/lib/gollum/public/gollum/javascript/editor/gollum.editor.js b/lib/gollum/public/gollum/javascript/editor/gollum.editor.js index 3b281e7f..b389f7a3 100755 --- a/lib/gollum/public/gollum/javascript/editor/gollum.editor.js +++ b/lib/gollum/public/gollum/javascript/editor/gollum.editor.js @@ -98,6 +98,52 @@ $('#gollum-editor-help').removeClass('jaws'); } } // EditorHas.functionBar + + if ( EditorHas.dragDropUpload() ) { + var $editorBody = $('#gollum-editor-body'); + var editorBody = $('#gollum-editor-body')[0]; + editorBody.ondragover = function(e) { + $editorBody.addClass('dragging'); + return false; + }; + editorBody.ondragleave = function() { + $editorBody.removeClass('dragging'); + return false; + }; + editorBody.ondrop = function(e) { + debug("dropped file"); + e.preventDefault(); + $editorBody.removeClass('dragging').addClass('uploading'); + + var file = e.dataTransfer.files[0], + formData = new FormData(); + formData.append('upload_dest', uploadDest); + formData.append('file', file); + + $.ajax({ + url: '/uploadFile', + data: formData, + cache: false, + contentType: false, + processData: false, + type: 'POST', + success: function(){ + $editorBody.removeClass('uploading'); + var text = '[[' + uploadDest + '/' + file.name + ']]'; + var pos = editorBody.selectionStart || 0; + editorBody.value = editorBody.value.substring(0, pos) + text + editorBody.value.substring(pos); + editorBody.selectionStart = pos + text.length; + editorBody.selectionEnd = pos + text.length; + }, + error: function(r, textStatus) { + alert('Error uploading file: ' + textStatus); + $editorBody.removeClass('uploading'); + } + }); + + return false; + }; + } // EditorHas.dragDropUpload } // EditorHas.baseEditorMarkup }; @@ -444,6 +490,17 @@ */ titleDisplayed: function() { return ( ActiveOptions.NewFile ); + }, + + + /** + * EditorHas.dragDropUpload + * True if the editor is supports drag and drop file uploads, false otherwise. + * + * @return boolean + */ + dragDropUpload: function() { + return $('#gollum-editor.uploads-allowed').length; } }; diff --git a/lib/gollum/templates/editor.mustache b/lib/gollum/templates/editor.mustache index 562b415d..aa5ce35b 100644 --- a/lib/gollum/templates/editor.mustache +++ b/lib/gollum/templates/editor.mustache @@ -1,4 +1,4 @@ -
+
{{#is_create_page}}
{{/is_create_page}} @@ -89,6 +89,10 @@
+
+ + Uploading file ... +
{{#header}} diff --git a/lib/gollum/views/latest_changes.rb b/lib/gollum/views/latest_changes.rb new file mode 100644 index 00000000..8707e489 --- /dev/null +++ b/lib/gollum/views/latest_changes.rb @@ -0,0 +1,90 @@ +module Precious + module Views + class LatestChanges < Layout + + attr_reader :wiki + + def title + "Latest Changes (Globally)" + end + + def versions + i = @versions.size + 1 + @versions.map do |v| + i -= 1 + { :id => v.id, + :id7 => v.id[0..6], + :num => i, + :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), + :date_full => v.authored_date, + :files => v.stats.files.map { |f,*rest| + page_path = extract_renamed_path_destination(f) + page_path = remove_page_extentions(page_path) + { :file => f, + :link => "#{page_path}/#{v.id}" + } + } + } + end + end + + def remove_page_extentions(page_path) + Gollum::Markup.formats.values.each do |format| + page_path = page_path.gsub(/\.#{format[:regexp]}$/, '') + end + return page_path + end + + def extract_renamed_path_destination(file) + 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 + + def next_link + end + end + end +end diff --git a/test/test_latest_changes_view.rb b/test/test_latest_changes_view.rb new file mode 100644 index 00000000..1af3ee53 --- /dev/null +++ b/test/test_latest_changes_view.rb @@ -0,0 +1,45 @@ +# ~*~ encoding: utf-8 ~*~ +require File.expand_path(File.join(File.dirname(__FILE__), 'helper')) +require File.expand_path '../../lib/gollum/views/latest_changes', __FILE__ + +context "Precious::Views::LatestChanges" do + include Rack::Test::Methods + + def app + Precious::App + end + + setup do + @path = cloned_testpath("examples/lotr.git") + @wiki = Gollum::Wiki.new(@path) + Precious::App.set(:gollum_path, @path) + Precious::App.set(:wiki_options, {:latest_changes_count => 10}) + end + + test "displays_latest_changes" do + get('/latest_changes') + body = last_response.body + assert body.include?('Charles Pence'), "/latest_changes should include the Author Charles Pence" + assert body.include?('60f12f4'), "/latest_changes should include the :latest_changes_count commit" + assert !body.include?('0ed8cbe'), "/latest_changes should not include more than latest_changes_count commits" + assert body.include?('Data-Two.csv'), "/latest_changes include links to modified files in #{body}" + assert body.include?('Hobbit.md'), "/latest_changes should include links to modified pages in #{body}" + assert body.include?('My-<b>Precious.md => My-Precious.md'), "/latest_changes should indicate renaming action in #{body}" + end + + test "extract destination file name in case of path renaming" do + view = Precious::Views::LatestChanges.new + assert_equal "newDirectoryName/fileName.md", view.extract_renamed_path_destination("{oldDirectoryName => newDirectoryName}/fileName.md") + end + + test "remove page extentions" do + view = Precious::Views::LatestChanges.new + assert_equal "page", view.remove_page_extentions("page.wiki") + assert_equal "page-wiki", view.remove_page_extentions("page-wiki.md") + assert_equal "file.any_extention", view.remove_page_extentions("file.any_extention") + end + + teardown do + FileUtils.rm_rf(@path) + end +end From b932763080926b6bfa92fd0c410fb536b0e02aa4 Mon Sep 17 00:00:00 2001 From: Roman Bambycha <2233965@gmail.com> Date: Mon, 17 Nov 2014 19:46:46 +0200 Subject: [PATCH 17/24] add function to disable editing, resolves #879 --- bin/gollum | 5 ++ lib/gollum/app.rb | 10 +++- lib/gollum/editing_auth.rb | 34 ++++++++++++ lib/gollum/helpers.rb | 12 ++++ lib/gollum/templates/compare.mustache | 26 +++++---- lib/gollum/templates/history.mustache | 6 +- lib/gollum/templates/page.mustache | 42 +++++++++----- lib/gollum/templates/pages.mustache | 7 ++- lib/gollum/views/compare.rb | 2 +- lib/gollum/views/history.rb | 2 +- lib/gollum/views/page.rb | 4 ++ lib/gollum/views/pages.rb | 2 +- test/test_allow_editing.rb | 80 +++++++++++++++++++++++++++ test/test_app.rb | 2 +- 14 files changed, 199 insertions(+), 35 deletions(-) create mode 100644 lib/gollum/editing_auth.rb create mode 100644 test/test_allow_editing.rb diff --git a/bin/gollum b/bin/gollum index d85a8cf8..330405b7 100755 --- a/bin/gollum +++ b/bin/gollum @@ -22,6 +22,7 @@ options = { 'port' => 4567, 'bind' => '0.0.0.0' } wiki_options = { :live_preview => false, :allow_uploads => false, + :allow_editing => true, } opts = OptionParser.new do |opts| @@ -76,6 +77,10 @@ opts = OptionParser.new do |opts| wiki_options[:ref] = ref end + opts.on("--no-edit", "Restricts editing capability through frontend.") do + wiki_options[:allow_editing] = false + end + opts.on("--no-live-preview", "Disables livepreview.") do wiki_options[:live_preview] = false end diff --git a/lib/gollum/app.rb b/lib/gollum/app.rb index a7de7750..b853a350 100644 --- a/lib/gollum/app.rb +++ b/lib/gollum/app.rb @@ -13,6 +13,8 @@ require 'gollum/views/has_page' require File.expand_path '../helpers', __FILE__ +require 'gollum/editing_auth' + #required to upload bigger binary files Gollum::set_git_timeout(120) Gollum::set_git_max_filesize(190 * 10**6) @@ -42,6 +44,7 @@ module Precious class App < Sinatra::Base register Mustache::Sinatra include Precious::Helpers + use Precious::EditingAuth dir = File.dirname(File.expand_path(__FILE__)) @@ -91,6 +94,8 @@ module Precious settings.wiki_options.merge!({ :base_path => @base_url }) @css = settings.wiki_options[:css] @js = settings.wiki_options[:js] + @mathjax_config = settings.wiki_options[:mathjax_config] + @allow_editing = settings.wiki_options[:allow_editing] end get '/' do @@ -105,7 +110,6 @@ module Precious # name, path, version def wiki_page(name, path = nil, version = nil, exact = true) wiki = wiki_new - path = name if path.nil? name = extract_name(name) || wiki.index_page path = extract_path(path) @@ -126,6 +130,7 @@ module Precious end get '/edit/*' do + forbid unless @allow_editing wikip = wiki_page(params[:splat].first) @name = wikip.name @path = wikip.path @@ -253,6 +258,7 @@ module Precious end get '/delete/*' do + forbid unless @allow_editing wikip = wiki_page(params[:splat].first) name = wikip.name wiki = wikip.wiki @@ -267,6 +273,7 @@ module Precious end get '/create/*' do + forbid unless @allow_editing wikip = wiki_page(params[:splat].first.gsub('+', '-')) @name = wikip.name.to_url @path = wikip.path @@ -476,6 +483,7 @@ module Precious elsif file = wiki.file(fullpath, wiki.ref, true) show_file(file) else + not_found unless @allow_editing page_path = [path, name].compact.join('/') redirect to("/create/#{clean_url(encodeURIComponent(page_path))}") end diff --git a/lib/gollum/editing_auth.rb b/lib/gollum/editing_auth.rb new file mode 100644 index 00000000..9d502658 --- /dev/null +++ b/lib/gollum/editing_auth.rb @@ -0,0 +1,34 @@ +module Precious + class EditingAuth < Sinatra::Base + def initialize(app) + @app = app + end + + def call(env) + @env = env + # Blocks all potentially editable pages. Use EditingAuth::whitelist_pages to unblock pages. + unless (env["REQUEST_METHOD"] == "GET") || App::settings.wiki_options[:allow_editing] + return block unless excluded_page? + end + @app.call(env) + end + + def block + [403, {'Content-Type' => 'text/html', 'Content-Length' => '9'}, ['Forbidden']] + end + + def excluded_page? + return false if env["REQUEST_PATH"].nil? + whitelist_pages.any? do |whitelisted_page| + env["REQUEST_PATH"].include? whitelisted_page + end + end + + private + # List pages paths as str that you want to whitelist. + # Pages will be compared with env["REQUEST_PATH"] using String::include? method. + def whitelist_pages + return ["/compare/"] + end + end +end \ No newline at end of file diff --git a/lib/gollum/helpers.rb b/lib/gollum/helpers.rb index 4fba20bf..ccda58e5 100644 --- a/lib/gollum/helpers.rb +++ b/lib/gollum/helpers.rb @@ -39,5 +39,17 @@ module Precious url.gsub('%2F', '/').gsub(/^\/+/, '').gsub('//', '/') end + def forbid(msg = "Forbidden.") + @message = msg + status 403 + halt mustache :error + end + + def not_found(msg = nil) + @message = msg || "The requested page does not exist." + status 404 + return mustache :error + end + end end diff --git a/lib/gollum/templates/compare.mustache b/lib/gollum/templates/compare.mustache index b180a6a8..da723978 100644 --- a/lib/gollum/templates/compare.mustache +++ b/lib/gollum/templates/compare.mustache @@ -8,8 +8,10 @@
  • View Page
  • -
  • Edit Page
  • + {{#allow_editing}} +
  • Edit Page
  • + {{/allow_editing}}
  • Page History
  • @@ -25,11 +27,13 @@ {{/show_revert}} @@ -52,9 +56,11 @@
  • Back to Page History
  • {{#show_revert}} -
  • - Revert Changes -
  • + {{#allow_editing}} +
  • + Revert Changes +
  • + {{/allow_editing}} {{/show_revert}}
  • Back to Top
  • diff --git a/lib/gollum/templates/history.mustache b/lib/gollum/templates/history.mustache index 17c2357e..342b878b 100644 --- a/lib/gollum/templates/history.mustache +++ b/lib/gollum/templates/history.mustache @@ -7,8 +7,10 @@
  • View Page
  • -
  • Edit Page
  • + {{#allow_editing}} +
  • Edit Page
  • + {{/allow_editing}}
    diff --git a/lib/gollum/templates/page.mustache b/lib/gollum/templates/page.mustache index d7b7a53a..5c4b8884 100644 --- a/lib/gollum/templates/page.mustache +++ b/lib/gollum/templates/page.mustache @@ -18,18 +18,28 @@ Mousetrap.bind(['e'], function( e ) { class="action-all-pages">All
  • Files
  • -
  • - New
  • - {{#allow_uploads}} -
  • - Upload
  • - {{/allow_uploads}} - {{#editable}} -
  • - Rename
  • -
  • Edit
  • - {{/editable}} + {{#allow_editing}} +
  • + New
  • + {{/allow_editing}} + {{#allow_editing}} + {{#allow_uploads}} +
  • + Upload
  • + {{/allow_uploads}} + {{/allow_editing}} + {{#allow_editing}} + {{#editable}} +
  • + Rename
  • + {{/editable}} + {{/allow_editing}} + {{#allow_editing}} + {{#editable}} +
  • Edit
  • + {{/editable}} + {{/allow_editing}} {{#page_exists}}
  • diff --git a/lib/gollum/templates/pages.mustache b/lib/gollum/templates/pages.mustache index 93e5e66d..7efc3dbe 100644 --- a/lib/gollum/templates/pages.mustache +++ b/lib/gollum/templates/pages.mustache @@ -7,9 +7,10 @@
  • Home
  • -
  • - New -
  • + {{#allow_editing}} +
  • + New
  • + {{/allow_editing}}
    diff --git a/lib/gollum/views/compare.rb b/lib/gollum/views/compare.rb index df2e3a3a..a8abca8e 100644 --- a/lib/gollum/views/compare.rb +++ b/lib/gollum/views/compare.rb @@ -3,7 +3,7 @@ module Precious class Compare < Layout include HasPage - attr_reader :page, :diff, :versions, :message + attr_reader :page, :diff, :versions, :message, :allow_editing def title "Comparison of #{@page.title}" diff --git a/lib/gollum/views/history.rb b/lib/gollum/views/history.rb index ca51254c..a3d19e3b 100644 --- a/lib/gollum/views/history.rb +++ b/lib/gollum/views/history.rb @@ -3,7 +3,7 @@ module Precious class History < Layout include HasPage - attr_reader :page, :page_num + attr_reader :page, :page_num, :allow_editing def title @page.title diff --git a/lib/gollum/views/page.rb b/lib/gollum/views/page.rb index c30210e3..beff30ad 100644 --- a/lib/gollum/views/page.rb +++ b/lib/gollum/views/page.rb @@ -47,6 +47,10 @@ module Precious @page_exists end + def allow_editing + @allow_editing + end + def allow_uploads @allow_uploads end diff --git a/lib/gollum/views/pages.rb b/lib/gollum/views/pages.rb index 0a8d77d4..bd020d2a 100644 --- a/lib/gollum/views/pages.rb +++ b/lib/gollum/views/pages.rb @@ -3,7 +3,7 @@ require "pathname" module Precious module Views class Pages < Layout - attr_reader :results, :ref + attr_reader :results, :ref, :allow_editing def title "All pages in #{@ref}" diff --git a/test/test_allow_editing.rb b/test/test_allow_editing.rb new file mode 100644 index 00000000..d59b93ba --- /dev/null +++ b/test/test_allow_editing.rb @@ -0,0 +1,80 @@ +# ~*~ encoding: utf-8 ~*~ +require File.expand_path(File.join(File.dirname(__FILE__), 'helper')) + +context "Precious::Views::Editing" do + include Rack::Test::Methods + setup do + examples = testpath "examples" + @path = File.join(examples, "test.git") + Precious::App.set(:gollum_path, @path) + FileUtils.cp_r File.join(examples, "revert.git"), @path, :remove_destination => true + @wiki = Gollum::Wiki.new(@path) + end + + teardown do + FileUtils.rm_r(File.join(File.dirname(__FILE__), *%w[examples test.git])) + end + + test "creating page is blocked" do + Precious::App.set(:wiki_options, { allow_editing: false}) + post "/create", :content => 'abc', :page => "D", + :format => 'markdown', :message => 'def' + assert !last_response.ok? + + page = @wiki.page('D') + assert page.nil? + end + + + test "frontend links for editing are not blocked" do + Precious::App.set(:wiki_options, { allow_editing: true, allow_uploads: true }) + get '/A' + + assert_match /Delete this Page/, last_response.body, "'Delete this Page' link is blocked in page template" + assert_match /New/, last_response.body, "'New' button is blocked in page template" + assert_match /Upload/, last_response.body, "'Upload' link is blocked in page template" + assert_match /Rename/, last_response.body, "'Rename' link is blocked in page template" + assert_match /Edit/, last_response.body, "'Edit' link is blocked in page template" + + get '/pages' + + assert_match /New/, last_response.body, "'New' link is blocked in pages template" + + get '/history/A' + + assert_match /Edit/, last_response.body, "'Edit' link is blocked in history template" + + get '/compare/A/fc66539528eb96f21b2bbdbf557788fe8a1196ac..b26b791cb7917c4f37dd9cb4d1e0efb24ac4d26f' + + assert_match /Edit Page/, last_response.body, "'Edit Page' link is blocked in compare template" + assert_match /Revert Changes/, last_response.body, "'Revert Changes' link is blocked in compare template" + end + + test "frontend links for editing blocked" do + Precious::App.set(:wiki_options, { allow_editing: false }) + get '/A' + + assert_no_match /Delete this Page/, last_response.body, "'Delete this Page' link not blocked in page template" + assert_no_match /New/, last_response.body, "'New' button not blocked in page template" + assert_no_match /Upload/, last_response.body, "'Upload' link not blocked in page template" + assert_no_match /Rename/, last_response.body, "'Rename' link not blocked in page template" + assert_no_match /Edit/, last_response.body, "'Edit' link not blocked in page template" + + get '/pages' + + assert_no_match /New/, last_response.body, "'New' link not blocked in pages template" + + get '/history/A' + + assert_no_match /Edit/, last_response.body, "'Edit' link not blocked in history template" + + get '/compare/A/fc66539528eb96f21b2bbdbf557788fe8a1196ac..b26b791cb7917c4f37dd9cb4d1e0efb24ac4d26f' + + assert_no_match /Edit Page/, last_response.body, "'Edit Page' link not blocked in compare template" + assert_no_match /Revert Changes/, last_response.body, "'Revert Changes' link not blocked in compare template" + end + + def app + Precious::App + end +end \ No newline at end of file diff --git a/test/test_app.rb b/test/test_app.rb index ffd0e7b3..ff0a5625 100644 --- a/test/test_app.rb +++ b/test/test_app.rb @@ -8,7 +8,7 @@ context "Frontend" do @path = cloned_testpath("examples/revert.git") @wiki = Gollum::Wiki.new(@path) Precious::App.set(:gollum_path, @path) - Precious::App.set(:wiki_options, {}) + Precious::App.set(:wiki_options, {allow_editing: true}) end teardown do From a832b0ed547aea214458bd7a00b1ed4a81c21730 Mon Sep 17 00:00:00 2001 From: Dawa Ometto Date: Tue, 25 Nov 2014 19:54:31 +0100 Subject: [PATCH 18/24] Fix tests, see https://github.com/gollum/gollum-lib/issues/112 --- test/test_app.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_app.rb b/test/test_app.rb index d4a99b9f..68c590e9 100644 --- a/test/test_app.rb +++ b/test/test_app.rb @@ -78,7 +78,7 @@ context "Frontend" do get page - expected = "

    #{text}

    " + expected = "

    #{text}

    " actual = nfd(last_response.body) assert_match /#{expected}/, actual From 57b7bbff5a293662ee3bc87b2b83bc6cb7e40c35 Mon Sep 17 00:00:00 2001 From: Dawa Ometto Date: Tue, 25 Nov 2014 23:43:42 +0100 Subject: [PATCH 19/24] Update README.md Updated command line options. --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 28dcbcb6..383aff3d 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Gollum follows the rules of [Semantic Versioning](http://semver.org/) and uses ## SECURITY -Don't enable `--custom-css` or `--custom-js` unless you trust every user who has the ability to edit the wiki. +Don't enable `--custom-css`, `--custom-js` or `--mathjax-config` unless you trust every user who has the ability to edit the wiki. A better solution with more security is being tracked in [#665](https://github.com/gollum/gollum/issues/665). ## INSTALLATION @@ -108,11 +108,12 @@ Options: --base-path [PATH] Specify the base path for the served pages (default: /) Example: --base-path wiki yields the home page accessible at http://localhost:4567/wiki/. --gollum-path [PATH] Specify the path to the git repository to be served. --ref [REF] Specify the repository ref to use (default: master). + --no-edit Restricts editing capability through frontend. --no-live-preview Disables livepreview. --live-preview Enables livepreview. --allow-uploads [MODE] Allows file uploads. Modes: dir (default, store all uploads in the same directory), page (store each upload at the same location as the page). --mathjax Enables mathjax for rendering mathematical equations. Uses the TeX-AMS-MML_HTMLorMML config with the autoload-all extension by default. - --mathjax-config [SOURCE] Inject custom mathjax config. Uses mathjax.config.js from root repository by default + --mathjax-config [SOURCE] Inject custom mathjax config file. Uses mathjax.config.js from root repository by default --user-icons [SOURCE] Set the history user icons. Valid values: gravatar, identicon, none. Default: none. --show-all Shows all files in file view. By default only valid pages are shown. --collapse-tree Collapse file view tree. By default, expanded tree is shown. From a776d9fb6f4be15e5288bf2403818cba78361aed Mon Sep 17 00:00:00 2001 From: Dawa Ometto Date: Wed, 26 Nov 2014 00:28:35 +0100 Subject: [PATCH 20/24] Implement git adapter CLI flag. --- README.md | 1 + bin/gollum | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/README.md b/README.md index 383aff3d..c3515285 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,7 @@ Options: --host [HOST] Hostname or IP address to listen on (default 0.0.0.0). --version Display current version. --config [CONFIG] Path to additional configuration file + --adapter [ADAPTER] Git adapter to use in the backend. Defaults to grit. --irb Start an irb process with gollum loaded for the current wiki. --css Inject custom css. Uses custom.css from root repository --js Inject custom js. Uses custom.js from root repository diff --git a/bin/gollum b/bin/gollum index 330405b7..9a5f32cc 100755 --- a/bin/gollum +++ b/bin/gollum @@ -45,6 +45,10 @@ opts = OptionParser.new do |opts| options['config'] = config end + opts.on("--adapter [ADAPTER]", "Git adapter to use in the backend. Defaults to grit.") do |adapter| + Gollum::GIT_ADAPTER = adapter + end + opts.on("--irb", "Start an irb process with gollum loaded for the current wiki.") do options['irb'] = true end From 8b8ef0eb46668a65dcd06c393a0714300ee2b0df Mon Sep 17 00:00:00 2001 From: Dawa Ometto Date: Thu, 27 Nov 2014 13:51:02 +0100 Subject: [PATCH 21/24] Prepare new release. --- gollum.gemspec | 13 +++++++------ lib/gollum.rb | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/gollum.gemspec b/gollum.gemspec index e22b77f6..0de31bda 100644 --- a/gollum.gemspec +++ b/gollum.gemspec @@ -5,8 +5,8 @@ Gem::Specification.new do |s| s.required_ruby_version = '>= 1.9' s.name = 'gollum' - s.version = '3.0.0' - s.date = '2014-04-05' + s.version = '3.1.0' + s.date = '2014-11-27' s.rubyforge_project = 'gollum' s.license = 'MIT' @@ -24,7 +24,7 @@ Gem::Specification.new do |s| s.rdoc_options = ['--charset=UTF-8'] s.extra_rdoc_files = %w[README.md LICENSE] - s.add_dependency 'gollum-lib', '~> 3.0' + s.add_dependency 'gollum-lib', '~> 4.0' s.add_dependency 'github-markdown', '~> 0.6.5' s.add_dependency 'sinatra', '~> 1.4', '>= 1.4.4' s.add_dependency 'mustache', ['>= 0.99.5', '< 1.0.0'] @@ -45,10 +45,14 @@ Gem::Specification.new do |s| Rakefile bin/gollum config.rb + contrib/openrc/conf.d/gollum + contrib/openrc/init.d/gollum + contrib/systemd/gollum@.service docs/sanitization.md gollum.gemspec lib/gollum.rb lib/gollum/app.rb + lib/gollum/editing_auth.rb lib/gollum/helpers.rb lib/gollum/public/gollum/css/_styles.css lib/gollum/public/gollum/css/dialog.css @@ -538,9 +542,6 @@ Gem::Specification.new do |s| licenses/css_tree_menu_thecssninja/license.txt licenses/licenses.txt licenses/unity_asset_pool/COPYRIGHT - contrib/openrc/conf.d/gollum - contrib/openrc/init.d/gollum - contrib/systemd/gollum@.service ] # = MANIFEST = diff --git a/lib/gollum.rb b/lib/gollum.rb index 70a2378a..179640ca 100644 --- a/lib/gollum.rb +++ b/lib/gollum.rb @@ -16,7 +16,7 @@ require File.expand_path('../gollum/uri_encode_component', __FILE__) $KCODE = 'U' if RUBY_VERSION[0, 3] == '1.8' module Gollum - VERSION = '3.0.0' + VERSION = '3.1.0' def self.assets_path ::File.expand_path('gollum/public', ::File.dirname(__FILE__)) From 861dc935cb951873aee552535907d4c177a64f09 Mon Sep 17 00:00:00 2001 From: Dawa Ometto Date: Thu, 27 Nov 2014 19:06:37 +0100 Subject: [PATCH 22/24] Configure git on Travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index ff17fd05..d37f5efc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,3 +6,4 @@ rvm: before_install: - sudo apt-get update - sudo apt-get install libicu-dev + - git config --global --add diff.renames copies From 508c255d0f43eda78fb98256a37a76bfffb5f188 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20Charignon?= Date: Fri, 28 Nov 2014 09:01:14 +0100 Subject: [PATCH 23/24] Update test to avoide being dependent on git configuration The previous test implementation was dependent on the git configuration: renames = copies It could then pass on a computer with that config but not passe on a different developpeur computer who could have a different git configuration. That new implementation is testing the same behaviour but at a lower level and is not dependent on the git configuration anymore. --- .travis.yml | 1 - test/test_latest_changes_view.rb | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index d37f5efc..ff17fd05 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,4 +6,3 @@ rvm: before_install: - sudo apt-get update - sudo apt-get install libicu-dev - - git config --global --add diff.renames copies diff --git a/test/test_latest_changes_view.rb b/test/test_latest_changes_view.rb index 1af3ee53..4883b223 100644 --- a/test/test_latest_changes_view.rb +++ b/test/test_latest_changes_view.rb @@ -24,11 +24,11 @@ context "Precious::Views::LatestChanges" do assert !body.include?('0ed8cbe'), "/latest_changes should not include more than latest_changes_count commits" assert body.include?('Data-Two.csv'), "/latest_changes include links to modified files in #{body}" assert body.include?('Hobbit.md'), "/latest_changes should include links to modified pages in #{body}" - assert body.include?('My-<b>Precious.md => My-Precious.md'), "/latest_changes should indicate renaming action in #{body}" 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") assert_equal "newDirectoryName/fileName.md", view.extract_renamed_path_destination("{oldDirectoryName => newDirectoryName}/fileName.md") end From 249eed5c2cfef5981c5a06ea8ae36cf4fb75ebb2 Mon Sep 17 00:00:00 2001 From: Dawa Ometto Date: Fri, 28 Nov 2014 13:26:47 +0100 Subject: [PATCH 24/24] Update HISTORY.md --- HISTORY.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index d6fd9ec8..695aef55 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,7 +1,16 @@ -# Next release candidate +# 3.1 / 2014-11-28 +* New features + * Drag-and-drop uploading in the editor [@lucas-clemente](https://github.com/lucas-clemente) + * Latest changes view [@etienneCharignon](https://github.com/etienneCharignon) (#707) + * Option `--no-edit` to disable editing from the web interface [@bambycha](https://github.com/bambycha) (#879) + * Option `--mathjax-config` to specify custom mathjax configuration [@hardywu](https://github.com/hardywu) (#842) * Major enhancements - * Made the Gollum theme responsive [rtrvrtg] (#831) + * Made the Gollum theme responsive [@rtrvrtg](https://github.com/rtrvrtg) (#831) + * Depends on new [gollum-lib](https://github.com/gollum/gollum-lib) `4.0.0` + * Allows specifiying [git adapter](https://github.com/gollum/gollum/wiki/Git-adapters) with `--adapter` [@bartkamphorst](https://github.com/bartkamphorst), [@dometto](https://github.com/dometto) +* Numerous bugfixes + * **NB**: please pass `--h1-title` if you do not want page titles to default to the page's filepath. See [here](https://github.com/gollum/gollum/wiki/Page-titles). # 2.4.11 / 2013-01-08