├── .gitignore ├── LICENSE ├── README.md ├── assets ├── javascripts │ ├── ImageGallery.js │ ├── initializers │ │ └── image-gallery.js.es6 │ └── lib │ │ └── discourse-markdown │ │ └── image-gallery.js.es6 └── stylesheets │ └── image-gallery.css ├── config ├── locales │ └── server.en.yml ├── locals │ └── server.en.yml └── settings.yml └── plugin.rb /.gitignore: -------------------------------------------------------------------------------- 1 | **/.DS_Store 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Corey Robertson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | discourse-image-gallery 2 | ======================= 3 | 4 | Image gallery plugin for [Discourse](http://discourse.org) 5 | 6 | Usage 7 | ===== 8 | 9 | In your posts, surround a series of images with `[gallery]` ... `[/gallery]` 10 | 11 | Installation 12 | ============ 13 | 14 | * Check out the project 15 | * Copy the `discourse-image-gallery` folder to your `plugins` directory inside Discourse. 16 | 17 | License 18 | ======= 19 | MIT 20 | -------------------------------------------------------------------------------- /assets/javascripts/ImageGallery.js: -------------------------------------------------------------------------------- 1 | (function($) { 2 | var buildImageGallery = function($gallery, opts) { 3 | stripNonImages($gallery, opts.allowableChildren); 4 | $gallery.find("img").wrap('
'); 5 | $gallery.find(".image-wrapper").css({ 6 | height: opts.dimensions.height, 7 | width: opts.dimensions.width 8 | }) 9 | 10 | $gallery.find("img").each(function() { 11 | if (this.complete) { 12 | var $this = $(this); 13 | scaleImage($this, opts.dimensions); 14 | centerImage($this, opts.dimensions); 15 | } else { 16 | this.onload = () => { 17 | var $this = $(this); 18 | scaleImage($this, opts.dimensions); 19 | centerImage($this, opts.dimensions); 20 | } 21 | } 22 | 23 | }); 24 | } 25 | 26 | var stripNonImages = function($element, allowableChildrenSelector) { 27 | $element.find(" > :not(" + allowableChildrenSelector + ")").remove(); 28 | } 29 | 30 | var scaleImage = function($image, dimensions) { 31 | var height = 0, width = 0, heightRatio = 1, widthRatio = 1, ratio = 1; 32 | 33 | height = parseInt($image.attr("height"), 10); 34 | width = parseInt($image.attr("width"), 10); 35 | 36 | if(isNaN(height)) { 37 | height = $image.height(); 38 | } 39 | if(isNaN(width)) { 40 | width = $image.width(); 41 | } 42 | 43 | heightRatio = Math.min(dimensions.height / height, 1); 44 | widthRatio = Math.min(dimensions.width / width, 1); 45 | 46 | ratio = Math.max(heightRatio, widthRatio); 47 | 48 | $image.attr("height", parseInt(height * ratio)); 49 | $image.attr("width", parseInt(width * ratio)); 50 | } 51 | 52 | var centerImage = function($image, dimensions) { 53 | var height = $image.attr("height"), 54 | width = $image.attr("width"); 55 | 56 | 57 | var heightOffset = parseInt((height - dimensions.height) / 2); 58 | var widthOffset = parseInt((width - dimensions.width) / 2); 59 | 60 | $image.css({ 61 | top: -1 * heightOffset, 62 | left: -1 * widthOffset 63 | }); 64 | } 65 | 66 | $.fn.ImageGallery = function(options) { 67 | var defaults = { dimensions: {width: 200, height: 200}, allowableChildren: "img" }, 68 | opts = $.extend(defaults, options || {}); 69 | 70 | return this.each(function() { 71 | buildImageGallery($(this), opts); 72 | }); 73 | }; 74 | })(jQuery); 75 | -------------------------------------------------------------------------------- /assets/javascripts/initializers/image-gallery.js.es6: -------------------------------------------------------------------------------- 1 | import { withPluginApi, decorateCooked } from 'discourse/lib/plugin-api'; 2 | 3 | export default { 4 | name: "image-gallery", 5 | initialize(container) { 6 | const siteSettings = container.lookup('site-settings:main'); 7 | const gallerySettings = { 8 | dimensions: { 9 | width: parseInt(siteSettings.image_gallery_thumbnail_width), 10 | height: parseInt(siteSettings.image_gallery_thumbnail_height) 11 | }, 12 | allowableChildren: siteSettings.image_gallery_allowable_children 13 | } 14 | 15 | const gallerizeWithSettings = ($elem) => { 16 | $('.image-gallery', $elem).removeClass('image-gallery').addClass('discourse-image-gallery').ImageGallery(gallerySettings); 17 | } 18 | 19 | const initializer = (api) => api.decorateCooked(gallerizeWithSettings); 20 | 21 | if (siteSettings.image_gallery_enabled) { 22 | withPluginApi('0.5', initializer, { noApi: () => decorateCooked(container, gallerizeWithSettings) }); 23 | } 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /assets/javascripts/lib/discourse-markdown/image-gallery.js.es6: -------------------------------------------------------------------------------- 1 | import { registerOption } from 'pretty-text/pretty-text'; 2 | 3 | registerOption((siteSettings, opts) => { 4 | opts.features['image-gallery'] = siteSettings.image_gallery_enabled; 5 | }); 6 | 7 | function insertGallery(_, gallery) { 8 | return `