diff --git a/app/assets/javascripts/crabgrass/cookies.js b/app/assets/javascripts/crabgrass/cookies.js new file mode 100644 index 0000000000000000000000000000000000000000..edcf20038174887339eb838853e5879d9e14951c --- /dev/null +++ b/app/assets/javascripts/crabgrass/cookies.js @@ -0,0 +1,21 @@ +(function () { + var selector = '.cookie_warning'; + document.observe("dom:loaded", function() { + function showIfCookiesDisabled(elem) { + // two seconds should be enough to read the cookie. + var expires = (new Date(Date.now() + 2000)).toGMTString(); + document.cookie = "are_cookies_enabled=1; expires=" + expires; + if (document.cookie.length == 0) { + elem.show(); + } + } + + $$(selector).each(showIfCookiesDisabled); + + document.on('modal:onComplete', function(event, elem) { + var warning = elem.down(selector); + if (warning) showIfCookiesDisabled(warning); + }); + }); +})(); + diff --git a/app/assets/javascripts/crabgrass/forms.js b/app/assets/javascripts/crabgrass/forms.js index 87b0e20dc22cb45c353feebea323349eb4004cde..428226f311704765fe49e7e1fbe09c0bdaa02f19 100644 --- a/app/assets/javascripts/crabgrass/forms.js +++ b/app/assets/javascripts/crabgrass/forms.js @@ -36,6 +36,28 @@ }); })(); +// submit enhancements +// +// submit a form with ctrl+enter +// + +(function() { + function keyHandler (event, element){ + var key = event.which || event.keyCode; + var input = element || event.currentTarget; + var button = input.form.select('.btn-primary').first(); + switch (key) { + default: + break; + case Event.KEY_RETURN: + if (event.ctrlKey) button.click(); + break; + } + } + + document.on('keydown', 'form textarea', keyHandler) +})(); + // Toggle the visibility of another element based on if a checkbox is checked or // not. Additionally, sets the focus to the first input or textarea that is visible. diff --git a/app/assets/javascripts/libraries/autocomplete.js b/app/assets/javascripts/libraries/autocomplete.js index c7382bbef1e731f4da2ba388352f147f79bcd9a6..91124996260ae4b82b955dd135ba3e0a9701488c 100644 --- a/app/assets/javascripts/libraries/autocomplete.js +++ b/app/assets/javascripts/libraries/autocomplete.js @@ -373,8 +373,15 @@ Autocomplete.prototype = { * display. */ appendSuggestions: function(response) { - this.suggestions = this.suggestions.concat(response.suggestions); - this.data = this.data.concat(response.data); + var suggestions = this.suggestions; + var data = this.data; + response.suggestions.each( function(value, i) { + var previous = suggestions.indexOf(value); + if (previous == -1) { + suggestions.push(value); + data.push(response.data[i]); + } + }); }, pending: 0, diff --git a/app/assets/javascripts/libraries/modalbox.js b/app/assets/javascripts/libraries/modalbox.js index 293870560745bd4125669cc1182c7bfe1d8106f6..38be3fdd3a7705cfe9d121c19e96215bb7437cc3 100644 --- a/app/assets/javascripts/libraries/modalbox.js +++ b/app/assets/javascripts/libraries/modalbox.js @@ -432,7 +432,10 @@ Modalbox.Methods = { event: function(eventName) { try { - if(this.options[eventName]) { + // cg addition: fire events like for ajax requests. + // these are easy to hook into. + var ev = this.MBwindow.fire("modal:" + eventName); + if(this.options[eventName] && !ev.stopped) { var returnValue = this.options[eventName](); // Executing callback this.options[eventName] = null; // Removing callback after execution if(returnValue != undefined) diff --git a/app/controllers/assets_controller.rb b/app/controllers/assets_controller.rb index cc6e091ef619666c80e27e7357d5e33bacc6e0b3..fceef7668bb4a3b9ee0a3d50216b35106baae753 100644 --- a/app/controllers/assets_controller.rb +++ b/app/controllers/assets_controller.rb @@ -32,6 +32,7 @@ class AssetsController < ApplicationController def destroy @asset.destroy + current_user.updated(@asset.page) respond_to do |format| format.js {render text: 'if (initAjaxUpload) initAjaxUpload();' } format.html do @@ -64,7 +65,7 @@ class AssetsController < ApplicationController end def thumb_name_from_path(path) - $~['thumb'].to_sym if path =~ /#{THUMBNAIL_SEPARATOR}(?<thumb>[a-z]+)\.[^\.]+$/ + $~['thumb'].to_sym if path =~ /#{THUMBNAIL_SEPARATOR}(?<thumb>[a-z]+)$/ end # returns 'inline' for formats that web browsers can display, 'attachment' otherwise. diff --git a/app/controllers/common/application/before_filters.rb b/app/controllers/common/application/before_filters.rb index 18b6453e8e2e036071b4801c05e4bdc45da53b72..e0fb53347989bad6471dfd758e354662d0598777 100644 --- a/app/controllers/common/application/before_filters.rb +++ b/app/controllers/common/application/before_filters.rb @@ -8,7 +8,7 @@ module Common::Application::BeforeFilters before_filter :header_hack_for_ie6 before_filter :redirect_unverified_user before_filter :enforce_ssl_if_needed - before_filter :setup_theme + before_render :setup_theme before_render :setup_context end @@ -77,7 +77,7 @@ module Common::Application::BeforeFilters # # overwrite if you want to handle permissions differently def authorized? - check_permissions + @authorized ||= check_permissions end # diff --git a/app/controllers/groups/avatars_controller.rb b/app/controllers/groups/avatars_controller.rb index 87c3d4ff556b67fc6d38812b7188119dc2d35a27..c5d9e7f4b7a64ee6a1cc5503e86a9ad6802e3877 100644 --- a/app/controllers/groups/avatars_controller.rb +++ b/app/controllers/groups/avatars_controller.rb @@ -3,7 +3,6 @@ class Groups::AvatarsController < Groups::BaseController include_controllers 'common/avatars' include_controllers 'common/always_perform_caching' before_filter :setup - skip_before_filter :login_required cache_sweeper :group_sweeper guard :allow diff --git a/app/controllers/groups/permissions_controller.rb b/app/controllers/groups/permissions_controller.rb index a1caecfd5007ab49493fdaf5b8f895caae8f837a..75e0ddfeb4cac0c7f777bda7c07b9a8a858c1ead 100644 --- a/app/controllers/groups/permissions_controller.rb +++ b/app/controllers/groups/permissions_controller.rb @@ -1,6 +1,5 @@ class Groups::PermissionsController < Groups::BaseController - before_filter :login_required helper 'castle_gates' def index diff --git a/app/controllers/groups/profiles_controller.rb b/app/controllers/groups/profiles_controller.rb index 049ccd90dde764c624d435355a4a122e886a5710..0d5134444fe40317b4c8271653e478f0a5780d3f 100644 --- a/app/controllers/groups/profiles_controller.rb +++ b/app/controllers/groups/profiles_controller.rb @@ -9,15 +9,11 @@ class Groups::ProfilesController < Groups::BaseController def update if params[:clear_photo] @profile.picture.destroy - success :profile_saved.t - redirect_to edit_group_profile_url(@group) else @profile.save_from_params profile_params - if @profile.valid? - success :profile_saved.t - redirect_to edit_group_profile_url(@group) - end end + success :profile_saved.t + redirect_to edit_group_profile_url(@group) end private diff --git a/app/controllers/me/profile_controller.rb b/app/controllers/me/profile_controller.rb index 8d5be5ce020b9643d8e3644fbf69857b7e926de5..a18a7a73ccc58a72adc8ffad8170d1bf65163bef 100644 --- a/app/controllers/me/profile_controller.rb +++ b/app/controllers/me/profile_controller.rb @@ -9,15 +9,11 @@ class Me::ProfileController < Me::BaseController def update if params[:clear_photo] @profile.picture.destroy - success :profile_saved.t - redirect_to edit_me_profile_path else - @profile.save_from_params params['profile'] - if @profile.valid? - success :profile_saved.t - redirect_to edit_me_profile_path - end + @profile.save_from_params profile_params end + success :profile_saved.t + redirect_to edit_me_profile_path end protected @@ -26,5 +22,9 @@ class Me::ProfileController < Me::BaseController @profile = current_user.profiles.public end + def profile_params + params[:profile].permit :place, :organization, :role, :summary, + {:picture => [:upload]} + end end diff --git a/app/controllers/pages/attributes_controller.rb b/app/controllers/pages/attributes_controller.rb index 3a2309941dcd120101ca80cbd35637eca07fc9a3..e70df589097cf92b3f2b903a268695aee2e863cf 100644 --- a/app/controllers/pages/attributes_controller.rb +++ b/app/controllers/pages/attributes_controller.rb @@ -22,7 +22,7 @@ class Pages::AttributesController < Pages::SidebarsController else owner = Group.find_by_name params[:owner] end - raise_not_found('owner') unless owner + raise_not_found(:owner.t) unless owner @page.owner = owner @page.save! redirect_to page_path(@page) diff --git a/app/controllers/pages/base_controller.rb b/app/controllers/pages/base_controller.rb index 0a77c0139fa7076dad1fb44147f0cbb270a5c441..0fddf61bdf03d692838c8319a223032aec960961 100644 --- a/app/controllers/pages/base_controller.rb +++ b/app/controllers/pages/base_controller.rb @@ -8,6 +8,7 @@ class Pages::BaseController < ApplicationController before_filter :login_required, except: :show before_filter :authorization_required + before_filter :bust_cache, only: :show permissions :pages guard :may_ACTION_page? guard print: :may_show_page? diff --git a/app/controllers/pages/before_filters.rb b/app/controllers/pages/before_filters.rb index b9fd2e01621f1d2122d51ac07389fbd05e5394d6..d43f3d1ba192d1c6e5132c813d58043406eed521 100644 --- a/app/controllers/pages/before_filters.rb +++ b/app/controllers/pages/before_filters.rb @@ -18,8 +18,8 @@ module Pages::BeforeFilters # def default_fetch_data @page ||= Page.find(params[:page_id] || params[:id]) - unless @page - raise_not_found(:thing_not_found.t(thing: :page.t)) + unless @page && may_show_page? + raise_not_found(:page.t) end if logged_in? @@ -74,6 +74,16 @@ module Pages::BeforeFilters end end + # ensure the page will be reloaded when navigated to in browser history + # why? because we use a bunch of ajax on the pages - for example when + # adding comments. It's really odd if these disappear when you navigate + # back. + def bust_cache + response.headers["Cache-Control"] = "no-cache, no-store, max-age=0, must-revalidate" + response.headers["Pragma"] = "no-cache" + response.headers["Expires"] = "Fri, 01 Jan 1990 00:00:00 GMT" + end + ## ## AFTER FILTERS ## diff --git a/app/controllers/pages/participations_controller.rb b/app/controllers/pages/participations_controller.rb index 4fcced29c0c29e5a2553c9c38c6b0309a593a5c2..92a30db7f81e97437f54d110262bb9fe263f086c 100644 --- a/app/controllers/pages/participations_controller.rb +++ b/app/controllers/pages/participations_controller.rb @@ -22,6 +22,7 @@ class Pages::ParticipationsController < Pages::SidebarsController elsif params[:star] star elsif params[:access] + raise_denied unless may_admin_page? access end end diff --git a/app/controllers/pages/posts_controller.rb b/app/controllers/pages/posts_controller.rb index b4d19adce09a20a790c145d68818e4b3fd515771..7fa12dd11b014be7f319d96031263ef2661fff35 100644 --- a/app/controllers/pages/posts_controller.rb +++ b/app/controllers/pages/posts_controller.rb @@ -7,7 +7,7 @@ class Pages::PostsController < ApplicationController helper 'pages/post' prepend_before_filter :fetch_data - before_filter :login_required + before_filter :login_required, except: :show before_filter :authorization_required guard :may_ALIAS_post? guard show: :may_show_page? diff --git a/app/controllers/pages/sidebars_controller.rb b/app/controllers/pages/sidebars_controller.rb index 1b3788ffbbdb00de902b8f45f169b52ad7abf0d1..dc67595d0fcd87a91f05879a321d89730d89af4d 100644 --- a/app/controllers/pages/sidebars_controller.rb +++ b/app/controllers/pages/sidebars_controller.rb @@ -5,6 +5,7 @@ class Pages::SidebarsController < ApplicationController before_filter :fetch_page + before_filter :login_required before_filter :authorization_required permissions :pages guard :may_edit_page? diff --git a/app/controllers/pages/tags_controller.rb b/app/controllers/pages/tags_controller.rb index a796d9da768648eddde9138a2ef5eebade025352..e425a54969d1fcb5b2e7c8f5952de48a6ff4f59c 100644 --- a/app/controllers/pages/tags_controller.rb +++ b/app/controllers/pages/tags_controller.rb @@ -1,6 +1,5 @@ class Pages::TagsController < Pages::SidebarsController - permissions 'pages' helper 'pages/tags' def index diff --git a/app/controllers/people/friend_requests_controller.rb b/app/controllers/people/friend_requests_controller.rb index be5002b6903c4cba4627466cd2b46dde0222c2d0..4f564bc489409695eb6b6bc78244b5ba35ed8e2c 100644 --- a/app/controllers/people/friend_requests_controller.rb +++ b/app/controllers/people/friend_requests_controller.rb @@ -1,5 +1,11 @@ class People::FriendRequestsController < People::BaseController + before_filter :login_required + + guard create: :may_request_contact?, + new: :may_request_contact?, + destroy: :may_remove_contact? + def new end @@ -24,15 +30,4 @@ class People::FriendRequestsController < People::BaseController redirect_to entity_url(@user) end - protected - - def authorized? - if action?('create', 'new') - may_request_contact? - elsif action?('destroy') - logged_in? && - current_user.friend_of?(@user) - end - end - end diff --git a/app/controllers/wikis/wikis_controller.rb b/app/controllers/wikis/wikis_controller.rb index bac8e4e684ba8ab58f814cb63f1520cc5b446b36..1cb7c144e2d2a30ad8778297bd6a1b3545a95801 100644 --- a/app/controllers/wikis/wikis_controller.rb +++ b/app/controllers/wikis/wikis_controller.rb @@ -55,6 +55,7 @@ class Wikis::WikisController < Wikis::BaseController if params[:save] || params[:force_save] version = params[:save] ? params[:wiki][:version] : nil # disable version checked if force save @wiki.update_section!(@section, current_user, version, params[:wiki][:body]) + current_user.updated(@page) success end end diff --git a/app/helpers/classes/context.rb b/app/helpers/classes/context.rb index c00c7348184ad2f3614f2135b94fc6ba39541854..4aab52a2703311c2e45187c3018cec34c3ee28e3 100644 --- a/app/helpers/classes/context.rb +++ b/app/helpers/classes/context.rb @@ -82,6 +82,10 @@ class Context self.breadcrumbs << object end + def banner_partial + '/layouts/context/normal_banner_content' + end + protected def define_crumbs() @@ -123,6 +127,11 @@ class Context::Committee < Context::Group push_crumb self.entity end end + + def banner_partial + '/layouts/context/nested_banner_content' + end + end class Context::Council < Context::Committee @@ -149,6 +158,17 @@ class Context::User < Context end end +class Context::UserGhost < Context::User + def define_crumbs + push_crumb :people + end + + def banner_partial + '/layouts/context/hidden_banner_content' + end + +end + class Context::Me < Context def self.wrapped_base_class ::User diff --git a/app/helpers/common/ui/help_helper.rb b/app/helpers/common/ui/help_helper.rb index 1dbd1c295a0e8044978b5e20902a8f61662efe0a..83b339b0ffd6e0102f2528b541f77d483e8b6a67 100644 --- a/app/helpers/common/ui/help_helper.rb +++ b/app/helpers/common/ui/help_helper.rb @@ -2,8 +2,13 @@ module Common::Ui::HelpHelper protected - def formatting_reference_link - (%Q{<a class="icon help_16" href="/do/static/greencloth" onclick="quickRedReference(); return false;">%s</a>} % :formatting_reference_link.t).html_safe + def formatting_reference_link(options = {}) + options.reverse_merge class: "icon help_16", + href: "/do/static/greencloth", + onclick: "quickRedReference(); return false;" + content_tag(:a, options) do + :formatting_reference_link.t + end end # returns the related help string, but only if it is translated. diff --git a/app/helpers/common/ui/layout_helper.rb b/app/helpers/common/ui/layout_helper.rb index c1cf1db93ba693655d6a2a964cea70e6dc6b14cc..58a8567e16774e2e474fca504bd02054d7f8e16b 100644 --- a/app/helpers/common/ui/layout_helper.rb +++ b/app/helpers/common/ui/layout_helper.rb @@ -50,12 +50,6 @@ module Common::Ui::LayoutHelper lines << optional_stylesheets.collect do |sheet| stylesheet_link_tag( current_theme.stylesheet_url(sheet) ) end - if context_banner_style || @content_for_style - lines << '<style type="text/css">' - lines << @content_for_style - lines << context_banner_style - lines << '</style>' - end lines << '<!--[if IE 6]>' lines << stylesheet_link_tag('ie6') lines << stylesheet_link_tag('icon_gif') diff --git a/app/helpers/common/ui/text_helper.rb b/app/helpers/common/ui/text_helper.rb index c0c5b0dead20cf66114fbd34bbdf969120574506..fa99fef7dca614e30ae80df02bf0c9c2c1803de5 100644 --- a/app/helpers/common/ui/text_helper.rb +++ b/app/helpers/common/ui/text_helper.rb @@ -49,6 +49,7 @@ module Common::Ui::TextHelper truncate(text, length: length, omission: omission + link) end + # def linked_activity_description(activity) # description = activity.try.safe_description(self) # expand_links(description) diff --git a/app/helpers/common/utility/context_helper.rb b/app/helpers/common/utility/context_helper.rb index e6791c93ce279dae0818b858d34f3fc502e66815..51562049e46076b14640819ec2745fb54ac412b9 100644 --- a/app/helpers/common/utility/context_helper.rb +++ b/app/helpers/common/utility/context_helper.rb @@ -1,4 +1,13 @@ module Common::Utility::ContextHelper + + # we only show the context if you either: + # * are allowed to do what you are doing + # * can see the context entity anyway (for error messages) + def visible_context? + @context && + ( @authorized || current_user.may?(:view, @context.entity) ) + end + # # sets up the navigation variables from the current theme. # @@ -33,7 +42,7 @@ module Common::Utility::ContextHelper end def context_class - @context.breadcrumbs.first if @context + @context.breadcrumbs.first if visible_context? end ## @@ -56,7 +65,7 @@ module Common::Utility::ContextHelper end "#banner_content {background-image: url(#{url}); background-color: #{bg}}\n"+ "#banner_content a.title {color: #{fg}; text-shadow: #{shadow} 0 0 2px}\n"+ - "ul#banner_nav_ul li.tab a.tab {background-color: #{nav_shade}}" + "ul#banner_nav_ul li.tab a.tab {color: #{fg}; background-color: #{nav_shade}}" else "#banner_content {background-image: url(#{url})}" end diff --git a/app/helpers/me/discussions_helper.rb b/app/helpers/me/discussions_helper.rb index 702cace13fecc34ae341df66d79cbd5c4caa9cfc..27f435a8d85a7525c563f768543911e365d835d6 100644 --- a/app/helpers/me/discussions_helper.rb +++ b/app/helpers/me/discussions_helper.rb @@ -7,10 +7,9 @@ module Me::DiscussionsHelper I18n.t(:message_user_wrote_caption, user: post.created_by.try.display_name) end - # remove surrounding <p> from body_html - html = post.body_html.try.gsub(/(\A\s*<p>)|(<\/p>\s*\Z)/, "") + preview = strip_tags(post.body_html).truncate(300).html_safe content_tag(:em, caption, class: "author_caption") + " \n" + - content_tag(:span, truncate(strip_links(html), length: 300), class: "post_body") + content_tag(:span, preview, class: "post_body") end ## diff --git a/app/helpers/profile_helper.rb b/app/helpers/profile_helper.rb index 2bc8c36d83cc835a7719eae53360ffb9e95137f8..a230df892cf94ca757934f5d959fe891febef401 100644 --- a/app/helpers/profile_helper.rb +++ b/app/helpers/profile_helper.rb @@ -4,26 +4,20 @@ module ProfileHelper formy.heading :banner.t if @profile.picture - formy.row do |r| - r.input clear_banner_input - end - else - formy.row do |r| - r.label I18n.t(:file) - r.label_for 'profile_picture_upload' - r.input file_field_tag('profile[picture][upload]', - id: 'profile_picture_upload') - r.info :banner_info.t( - optimal_dimensions: "#{banner_width.to_i} x #{banner_height.to_i}" - ) + formy.row(class: :current_banner) do |r| + r.input picture_tag(@profile.picture, :medium) end end + formy.row do |r| + r.label I18n.t(:file) + r.label_for 'profile_picture_upload' + r.input file_field_tag('profile[picture][upload]', + id: 'profile_picture_upload') + r.info :banner_info.t( + optimal_dimensions: "#{banner_width.to_i} x #{banner_height.to_i}" + ) + end end - def clear_banner_input - [ picture_tag(@profile.picture, :medium), - submit_tag("Clear", name: 'clear_photo') - ].join '<br/>' - end end diff --git a/app/helpers/wikis/sections_helper.rb b/app/helpers/wikis/sections_helper.rb index a3cd7e641e922aa2fea25cd5b27e30ad29ddaff3..94c3e0ce7509571b510f73cdc258b791a20773f9 100644 --- a/app/helpers/wikis/sections_helper.rb +++ b/app/helpers/wikis/sections_helper.rb @@ -4,7 +4,7 @@ module Wikis::SectionsHelper doc = Hpricot(wiki.body_html) doc.search('h4 a.anchor, h3 a.anchor, h2 a.anchor, h1 a.anchor').each do |anchor| subsection = anchor['href'].sub(/^.*#/, '') - add_edit_link_to_heading(wiki, anchor, subsection) + add_edit_link_to_heading(wiki, anchor, subsection) if wiki.edit_sections? wrap_in_div(wiki, doc, subsection, section == :document) end doc.to_html.html_safe diff --git a/app/models/asset.rb b/app/models/asset.rb index 8897bd6f286b14c3c6065b74509c02122acf5699..712cb0c7198f9444d0c135e2f4edd3b8071478a6 100644 --- a/app/models/asset.rb +++ b/app/models/asset.rb @@ -178,6 +178,9 @@ class Asset < ActiveRecord::Base medium = nil if small && medium && medium.size == small.size [small, medium, large].compact end + def other_formats + self.select{|t| !['small', 'medium', 'large'].include?(t.name)} + end end base.define_thumbnails( {} ) # root Asset class has no thumbnails end diff --git a/app/models/associations/group_participation.rb b/app/models/associations/group_participation.rb index d6d87254ee9a44b80cd229307c4fc50aae682fe0..ae2cad7a6781822016e1135f62a53af8e0f421bd 100644 --- a/app/models/associations/group_participation.rb +++ b/app/models/associations/group_participation.rb @@ -19,6 +19,7 @@ class GroupParticipation < ActiveRecord::Base # this includes the ability to find featured-pages in GroupParticipation # include GroupParticipationExtension::Featured include GroupParticipationExtension::PageHistory + include ParticipationAccess belongs_to :page, inverse_of: :group_participations belongs_to :group, inverse_of: :participations @@ -31,28 +32,4 @@ class GroupParticipation < ActiveRecord::Base group end - def access_sym - ACCESS_TO_SYM[self.access] - end - - # can only be used to increase access, not remove it. - def grant_access=(value) - value = ACCESS[value.to_sym] if value.is_a?(Symbol) or value.is_a?(String) - if value - if read_attribute(:access) - if read_attribute(:access) > value - write_attribute(:access, value) - end - else - write_attribute(:access, value) - end - end - end - - # can be used to add or remove access - def access=(value) - value = ACCESS[value] if value.is_a? Symbol or value.is_a?(String) - write_attribute(:access, value) - end - end diff --git a/app/models/associations/participation_access.rb b/app/models/associations/participation_access.rb new file mode 100644 index 0000000000000000000000000000000000000000..954554cf9080bead53e2e63053a1e3fdadf31183 --- /dev/null +++ b/app/models/associations/participation_access.rb @@ -0,0 +1,32 @@ +module ParticipationAccess + + def access_sym + ACCESS_TO_SYM[self.access] + end + + # can only be used to increase access. + # because access is only increased, you cannot remove access with grant_access. + def grant_access=(value) + value = ACCESS[value] if ACCESS.has_key?(value) + return if value.nil? + current_access = read_attribute(:access) || 100 + if value < current_access + write_attribute(:access, value) + end + end + + # sets the access level to be value, regardless of what it was before. + # if value is nil, no change is made. If value is :none, then access is removed. + def access=(value) + return if value.nil? + value = ACCESS[value] if ACCESS.has_key?(value) + write_attribute(:access, value) + end + + def grants_access?(perm) + asked_access_level = ACCESS[perm] || ACCESS[:view] + return false unless self.access + self.access <= asked_access_level + end + +end diff --git a/app/models/associations/user_participation.rb b/app/models/associations/user_participation.rb index e1ab3167512bb6e311c4d1300c804d3d1de7255f..211de7b3a96ecf36f32bb2910ccff899df2687e5 100644 --- a/app/models/associations/user_participation.rb +++ b/app/models/associations/user_participation.rb @@ -14,6 +14,8 @@ # class UserParticipation < ActiveRecord::Base + include ParticipationAccess + belongs_to :page, inverse_of: :user_participations belongs_to :user, inverse_of: :participations @@ -34,31 +36,6 @@ class UserParticipation < ActiveRecord::Base user end - def access_sym - ACCESS_TO_SYM[self.access] - end - - # can only be used to increase access. - # because access is only increased, you cannot remove access with grant_access. - def grant_access=(value) - value = ACCESS[value] if value.is_a?(Symbol) or value.is_a?(String) - if value - if read_attribute(:access) - write_attribute(:access, [value,read_attribute(:access)].min ) - else - write_attribute(:access, value) - end - end - end - - # sets the access level to be value, regardless of what it was before. - # if value is nil, no change is made. If value is :none, then access is removed. - def access=(value) - return if value.nil? - value = ACCESS[value] if value.is_a? Symbol or value.is_a?(String) - write_attribute(:access, value) - end - protected def clear_tag_cache diff --git a/app/models/discussion/discussion.rb b/app/models/discussion/discussion.rb index 6f118a83a2227f3e8cd7fadfb6a2d6c143330bd3..11d17d8738b45c74dad6749100fe6c8798074fee 100644 --- a/app/models/discussion/discussion.rb +++ b/app/models/discussion/discussion.rb @@ -143,8 +143,11 @@ class Discussion < ActiveRecord::Base last_post: post, replied_by_id: post.user_id, replied_at: post.updated_at ) - PrivateMessageNotice.create!(user: post.discussion.user_talking_to(post.user), message: post.body_html, from: post.user) if post.private? - + if post.private? + PrivateMessageNotice.create! from: post.user, + user: post.discussion.user_talking_to(post.user), + message: post.body_html + end end # diff --git a/app/models/discussion/post.rb b/app/models/discussion/post.rb index b9a03afe107e6e2a655634a335b24b26f4876181..a3146801e7292948ec1ea002ecc2fd55ca3c1bb6 100644 --- a/app/models/discussion/post.rb +++ b/app/models/discussion/post.rb @@ -110,10 +110,6 @@ class Post < ActiveRecord::Base return post end - def body_html - read_attribute(:body_html).try :html_safe - end - # used for default context, if present, to set for any embedded links def owner_name discussion.page.owner_name if discussion.page diff --git a/app/models/notice/notice.rb b/app/models/notice/notice.rb index e1811521f28eb0b4809fd9d2a4a3b7c3055e762c..72578e07bccfac2e699541506a87b3cc687c4702 100644 --- a/app/models/notice/notice.rb +++ b/app/models/notice/notice.rb @@ -102,6 +102,10 @@ class Notice < ActiveRecord::Base I18n.t(data[attr], count: 1) end end + rescue + Rails.logger.error "Invalid attribute #{attr} in Notice ##{id}." + Rails.logger.debug "value: " + data[attr].inspect + raise end end diff --git a/app/models/notice/page_update_notice.rb b/app/models/notice/page_update_notice.rb new file mode 100644 index 0000000000000000000000000000000000000000..b0733b39cece1d377589781e16721da6a3a6fa26 --- /dev/null +++ b/app/models/notice/page_update_notice.rb @@ -0,0 +1,19 @@ +class PageUpdateNotice < PageNotice + + def display_title + I18n.t("page_updated", data).html_safe + end + + def display_body_as_quote? + false + end + + def display_body + "" + end + + def display_label + I18n.t "page_update" + end + +end diff --git a/app/models/notice/private_message_notice.rb b/app/models/notice/private_message_notice.rb index b6ece6c405cb3550a4635a6ea6ba5355b2d58ed9..109bc73473051a54896b67fad5a22f4836396fb5 100644 --- a/app/models/notice/private_message_notice.rb +++ b/app/models/notice/private_message_notice.rb @@ -30,9 +30,7 @@ class PrivateMessageNotice < Notice end def display_body - # this is now post.body_html - # it's html safe because it's the Greencloth output. - data[:message].html_safe + data[:message] end def button_text diff --git a/app/models/notice/request_notice.rb b/app/models/notice/request_notice.rb index 1e4ef2b98b43e16ecec3c517c4443fba7c0e88e5..26e4b6a46956255cbe69fadef7db085015ce7f68 100644 --- a/app/models/notice/request_notice.rb +++ b/app/models/notice/request_notice.rb @@ -1,7 +1,7 @@ class RequestNotice < Notice alias_attr :request, :noticable - + class << self alias_method :find_all_by_request, :find_all_by_noticable alias_method :destroy_all_by_request, :destroy_all_by_noticable @@ -23,7 +23,7 @@ class RequestNotice < Notice else create!(request: request, user: request.recipient) end - end + end end end @@ -31,7 +31,7 @@ class RequestNotice < Notice def button_text :show_thing.t(thing: :request.t) end - + def display_label :request.t end @@ -53,7 +53,9 @@ class RequestNotice < Notice before_create :set_avatar def set_avatar - self.avatar_id = request.icon_entity.avatar_id if request.icon_entity + # we always display the person issuing the request. + # That way it matches the message notification + self.avatar_id = request.created_by.avatar_id end end diff --git a/app/models/page.rb b/app/models/page.rb index 348929d25fd7b367f3b502a595ee1d4ff97db581..a46394edb93bbd8ff7c9e05316534e11acad95bd 100644 --- a/app/models/page.rb +++ b/app/models/page.rb @@ -277,11 +277,11 @@ class Page < ActiveRecord::Base # This method should never be called directly. It should only be called # from User#may?() # - # possible permissions: + # possible access levels on participation objects: + # :none -- always returns false # :view -- user can see the page. # :edit -- user can participate. # :admin -- user can destroy the page, change access. - # :none -- always returns false # # :view should only return true if the user has access to view the page # because of participation objects, NOT because the page is public. @@ -297,16 +297,9 @@ class Page < ActiveRecord::Base ## END TEMP HACKS ######################################################### - asked_access_level = ACCESS[perm] || ACCESS[:view] participation = most_privileged_participation_for(user) - allowed = if participation.nil? - false - else - actual_access_level = participation.access || ACCESS[:view] - asked_access_level >= actual_access_level - end - - allowed ? true : raise(PermissionDenied.new) + allowed = participation.present? && participation.grants_access?(perm) + allowed || raise(PermissionDenied.new) end # returns the participation object for entity with the highest access level. diff --git a/app/models/page_extension/users.rb b/app/models/page_extension/users.rb index 6805d46f6e7e59068adc8589089cb94400c095d8..47dd729fc857bb9ec4a6759842f0be3d9127fd49 100644 --- a/app/models/page_extension/users.rb +++ b/app/models/page_extension/users.rb @@ -106,6 +106,7 @@ module PageExtension::Users # timestamp of the last visit of a user # def last_visit_of(user) + return nil unless user.real? user_participations.where(user_id: user).first.try.viewed_at end diff --git a/app/models/profile/profile.rb b/app/models/profile/profile.rb index d7ef5ae3ac16db9f9ecece1f003826d6013d8af8..d14f6bcff9e3c4b4f3d717cec553c55a10eb30f1 100644 --- a/app/models/profile/profile.rb +++ b/app/models/profile/profile.rb @@ -200,9 +200,9 @@ class Profile < ActiveRecord::Base end || [] rescue [] end - if params['picture'] - picture = params.delete('picture') - params['picture'] = Picture.new(picture) if picture['upload'] + picture_params = params.delete('picture') + if picture_params && picture_params['upload'] + params['picture'] = Picture.new(picture_params) end params['video'] = ExternalVideo.new(params.delete('video')) if params['video'] @@ -223,8 +223,13 @@ class Profile < ActiveRecord::Base end self.update_attributes( params ) - self.reload + self.reload # huh? why is this needed? self + rescue ErrorMessage + # In case the picture update did not work... let's keep the old one. + self.picture_id = self.picture_id_was + # still raise the error message + raise end def cover diff --git a/app/models/profile/profile_email_address.rb b/app/models/profile/profile_email_address.rb index 6d595b99371ce5a561c9725226edf5608996e913..c39fd3143955e1268aa7e6725b2447d867821004 100644 --- a/app/models/profile/profile_email_address.rb +++ b/app/models/profile/profile_email_address.rb @@ -4,7 +4,7 @@ class ProfileEmailAddress < ActiveRecord::Base - set_table_name 'email_addresses' + self.table_name = 'email_addresses' validates_presence_of :email_type validates :email_address, presence: true diff --git a/app/models/profile/profile_im_address.rb b/app/models/profile/profile_im_address.rb index 8e1719b9ad0da06ad4a2de96e777bb29d296f5e1..a8476eefabab284a66e85bce3479f2633f5000f4 100644 --- a/app/models/profile/profile_im_address.rb +++ b/app/models/profile/profile_im_address.rb @@ -4,7 +4,7 @@ class ProfileImAddress < ActiveRecord::Base - set_table_name 'im_addresses' + self.table_name = 'im_addresses' validates_presence_of :im_type validates_presence_of :im_address diff --git a/app/models/profile/profile_location.rb b/app/models/profile/profile_location.rb index 8cb487e9f40cc83f6d8016da3d13dad2eff40570..1d8fd5b777ef0d13996f800c1f6d0d0d76f62930 100644 --- a/app/models/profile/profile_location.rb +++ b/app/models/profile/profile_location.rb @@ -4,7 +4,7 @@ class ProfileLocation < ActiveRecord::Base - set_table_name 'locations' + self.table_name = 'locations' belongs_to :profile diff --git a/app/models/profile/profile_note.rb b/app/models/profile/profile_note.rb index b53effe8b72783bb69c547b6e6f1fa8715fa1141..3e449ee8183074e209fca129cdca6f6e14ff1653 100644 --- a/app/models/profile/profile_note.rb +++ b/app/models/profile/profile_note.rb @@ -4,7 +4,7 @@ class ProfileNote < ActiveRecord::Base validates_presence_of :body - set_table_name 'profile_notes' + self.table_name = 'profile_notes' belongs_to :profile diff --git a/app/models/profile/profile_phone_number.rb b/app/models/profile/profile_phone_number.rb index 45579413a68df89ef30001159249e719f3fcb7b1..a2357dbb0539ed0d4719898a89c6845c2c25da59 100644 --- a/app/models/profile/profile_phone_number.rb +++ b/app/models/profile/profile_phone_number.rb @@ -4,7 +4,7 @@ class ProfilePhoneNumber < ActiveRecord::Base - set_table_name 'phone_numbers' + self.table_name = 'phone_numbers' validates_presence_of :phone_number_type validates_presence_of :phone_number diff --git a/app/models/profile/profile_website.rb b/app/models/profile/profile_website.rb index ac654b3efd43187eb6708fef3af85dcfcd816460..be11b504b643c8f514ce17af51c04e10502dacab 100644 --- a/app/models/profile/profile_website.rb +++ b/app/models/profile/profile_website.rb @@ -4,7 +4,7 @@ class ProfileWebsite < ActiveRecord::Base - set_table_name 'websites' + self.table_name = 'websites' validates_presence_of :site_title validates_presence_of :site_url diff --git a/app/models/unauthenticated_user.rb b/app/models/unauthenticated_user.rb index 06873c504bb544252e2eddf2ff60bc25ee257ed3..4fd7547d5210c6ae5882ca60d93269d9d3cac319 100644 --- a/app/models/unauthenticated_user.rb +++ b/app/models/unauthenticated_user.rb @@ -14,8 +14,6 @@ class UnauthenticatedUser # nothing but viewing for now. return false unless access == :view case thing - when Page - access == :view and thing.public? when Group, User thing.has_access?(access, self) else diff --git a/app/models/user.rb b/app/models/user.rb index dc990a44c6c5e999a174cf4362e9bd60eb78405e..c9482cad9bc82d321e1ea959bbf15816a07342a1 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -17,7 +17,7 @@ class User < ActiveRecord::Base ## include Crabgrass::Validations - validates_handle :login + validates_handle :login, unless: :ghost? before_validation :validates_receive_notifications @@ -31,6 +31,7 @@ class User < ActiveRecord::Base presence: {if: :should_validate_email} def should_validate_email + return false if ghost? if Site.current Site.current.require_user_email else @@ -182,6 +183,11 @@ class User < ActiveRecord::Base return User.find(self.id) end + # overwritten in user_ghost + def ghost? + false + end + ## ## PROFILE ## diff --git a/app/models/user_extension/authenticated_user.rb b/app/models/user_extension/authenticated_user.rb index 13758adb224d1d992d890149d0d21106f8c4f60b..a19519be5ed7326003c961b03df74f5f7fcf6231 100644 --- a/app/models/user_extension/authenticated_user.rb +++ b/app/models/user_extension/authenticated_user.rb @@ -38,7 +38,7 @@ module AuthenticatedUser # the current site (set tmp on a per-request basis) attr_accessor :current_site - validates_presence_of :login + validates_presence_of :login, unless: :ghost? validates_presence_of :password, if: :password_required? validates_presence_of :password_confirmation, if: :password_required? validates_confirmation_of :password, if: :password_required? diff --git a/app/models/user_extension/pages.rb b/app/models/user_extension/pages.rb index 25186f2b85b073648b3ff727cbdee6f61e536914..e445a28af3a13df718fb632ed84529e1d20f75ed 100644 --- a/app/models/user_extension/pages.rb +++ b/app/models/user_extension/pages.rb @@ -143,7 +143,7 @@ module UserExtension::Pages # :all_resolved -- everyone's participation is resolved. # def updated(page, options={}) - raise PermissionDenied.new unless self.may?(:edit, page) + return if page.blank? now = Time.now unless page.contributor?(self) @@ -168,6 +168,9 @@ module UserExtension::Pages page.resolved = options[:all_resolved] || page.resolved? page.updated_at = now page.updated_by = self + page.user_participations.where(watch: true).each do |part| + PageUpdateNotice.create!(user_id: part.user_id, page: page, from: self) + end end ## diff --git a/app/models/user_ghost.rb b/app/models/user_ghost.rb index 065a928cfd20d9c940e5a8843eb25ec1cd265ff3..5931e23fdc6369f49a5825dde062d62fc17237ad 100644 --- a/app/models/user_ghost.rb +++ b/app/models/user_ghost.rb @@ -1,14 +1,8 @@ class UserGhost < User - def name - if read_attribute(:display_name).nil? - :anonymous.t - else - read_attribute(:display_name) - end + def login + read_attribute(:login).presence || :anonymous.t end - alias :login :name - alias :display_name :login # # retire this user. @@ -18,14 +12,15 @@ class UserGhost < User # 3. removes user data like profiles # def retire! - clean_attributes avatar.destroy if avatar - profiles.each { |p| p.destroy } # setting.destroy #TODO not sure if settings are ever used. - task_participations.each { |t| t.destroy } - participations.each { |p| p.destroy } - memberships.each { |m| m.destroy } # should we use remove_user! ? + profiles.destroy_all + task_participations.destroy_all + participations.destroy_all + memberships.destroy_all # should we use remove_user! ? relationships.each { |relationship| self.remove_contact!(User.find(relationship.contact_id)) } + keys.destroy_all + clean_attributes clear_cache end #handle_asynchronously :retire! @@ -34,7 +29,7 @@ class UserGhost < User # gets rid of the users name # def anonymize! - self.update_attribute(:display_name, nil) + self.update_attributes(display_name: nil, login: nil) end #handle_asynchronously :anonymize! @@ -46,21 +41,28 @@ class UserGhost < User end #handle_asynchronously :destroy_comments! + # can't do anything with a user_ghost + def has_access!(_perm, _user) + false + end + + def ghost? + true + end + + def password_required? + false + end + private def clean_attributes - # - # use update_attribute to bypass the validations - # - attrs_to_nil_out = %w( - crypted_password salt time_zone email - login created_at version - last_seen_at language remember_token remember_token_expires_at - updated_at - ) # updated_at should be last so it isn't re-set - attrs_to_nil_out.each do |attr| - update_attribute(attr, nil) - end + attrs_to_keep = %w(id type login display_name) + clean_attrs = attributes.except(*attrs_to_keep) + clean_attrs.each { |k, _v| clean_attrs[k] = nil } + update_attributes clean_attrs + # updated_at should be last so it isn't re-set + update_attribute("updated_at", nil) end end diff --git a/app/models/wiki.rb b/app/models/wiki.rb index b633d677e0cde8b7dd74cfd3b4e29cb6d33f820f..7eca92f97ce1623957e1e8b0cf70d688b0f121fe 100644 --- a/app/models/wiki.rb +++ b/app/models/wiki.rb @@ -119,7 +119,7 @@ class Wiki < ActiveRecord::Base # will render if not up to date def body_html update_body_html_and_structure - read_attribute(:body_html).html_safe + read_attribute(:body_html).try.html_safe end # will calculate structure if not up to date @@ -134,6 +134,10 @@ class Wiki < ActiveRecord::Base @structure ||= WikiExtension::WikiStructure.new(raw_structure, body.to_s) end + def edit_sections? + structure.sections.present? + end + # sets the block used for rendering the body to html def render_body_html_proc &block @render_body_html_proc = block @@ -249,7 +253,7 @@ class Wiki < ActiveRecord::Base end # returns html for wiki body - # user render_body_html_proc if available + # uses render_body_html_proc if available # or default GreenCloth rendering otherwise def render_body_html if @render_body_html_proc @@ -261,6 +265,10 @@ class Wiki < ActiveRecord::Base def render_raw_structure GreenCloth.new(body.to_s).to_structure + rescue GreenClothException => e + Rails.logger.error e + # let's return a dummy structure at least. + GreenCloth.new('').to_structure end class Version < ActiveRecord::Base @@ -289,7 +297,7 @@ class Wiki < ActiveRecord::Base end def body_html - read_attribute(:body_html).try :html_safe + read_attribute(:body_html).try.html_safe end end diff --git a/app/models/wiki_extension/wiki_structure.rb b/app/models/wiki_extension/wiki_structure.rb index 355d19413bc4512017a496cc08f7025e497e26c2..86887c337d6851a74e67c59b1a80c86a0c76f15b 100644 --- a/app/models/wiki_extension/wiki_structure.rb +++ b/app/models/wiki_extension/wiki_structure.rb @@ -17,6 +17,10 @@ module WikiExtension [:document] + green_tree.section_names end + def sections + green_tree.section_names + end + def update_body(section, section_body) find(section).sub_markup(section_body) end diff --git a/app/permissions/pages_permission.rb b/app/permissions/pages_permission.rb index cf1d3edf25201a79690258aa94cb2e2eb35e32e3..fa9509503988220fc8b106833d3712a48fc5d808 100644 --- a/app/permissions/pages_permission.rb +++ b/app/permissions/pages_permission.rb @@ -11,7 +11,7 @@ module PagesPermission # but the permission will still be checked here. # So we need to make sure users who do not have explicit # access the page can still see it if it's public. - !page or page.public? or current_user.may?(:view, page) + page.public? || current_user.may?(:view, page) end def may_edit_page?(page = @page) diff --git a/app/permissions/people_permission.rb b/app/permissions/people_permission.rb index 91eb9bdbf5f974fa9122ba467dcc0ee8084a4d64..7d6afad0450ecc316d8840966e17a974e4a4b313 100644 --- a/app/permissions/people_permission.rb +++ b/app/permissions/people_permission.rb @@ -19,4 +19,8 @@ module PeoplePermission current_user != @user end + def may_remove_contact? + current_user.friend_of?(@user) + end + end diff --git a/app/permissions/posts_permission.rb b/app/permissions/posts_permission.rb index 9ba15d2a944a6532110b2728bc03a83b58e41010..201aa2a6daf7fd5559f6a072efdfbbdc9f4847fc 100644 --- a/app/permissions/posts_permission.rb +++ b/app/permissions/posts_permission.rb @@ -3,17 +3,15 @@ module PostsPermission protected def may_create_post? - return false unless logged_in? if @recipient current_user.may?(:pester, @recipient) elsif @page - current_user.may?(:edit, @page) or - ( current_user.may?(:view, @page) and @page.public_comments? ) + current_user.may?(:view, @page) or + ( @page.public? && @page.public_comments? && logged_in? ) end end def may_edit_post?(post=@post) - logged_in? and post and post.user_id == current_user.id end @@ -21,7 +19,6 @@ module PostsPermission alias_method :may_update_post?, :may_edit_post? def may_twinkle_posts?(post=@post) - logged_in? and post.discussion.page and current_user.may?(:view, post.discussion.page) and current_user.id != post.user_id diff --git a/app/stylesheets/layout/banner.scss b/app/stylesheets/layout/banner.scss index ded5c74bd0ebb1c0bbb178d32ed4d9cb4ae7a23d..ca7f3be80cca2f05623fa340726cfec3236ade1a 100644 --- a/app/stylesheets/layout/banner.scss +++ b/app/stylesheets/layout/banner.scss @@ -84,9 +84,13 @@ $base_margin: ($avatar_border_width * 2) + (($banner_padding - border_width($ban // } } - a.title { + .title { color: $banner_default_foreground; font-size: $banner_font_size; + line-height: 1.8; + } + + a.title { @include cg-hover-link; } } @@ -172,7 +176,9 @@ $base_margin: ($avatar_border_width * 2) + (($banner_padding - border_width($ban // height: 32px; // width: 32px; //} - a.title {font-size: 1.1em;} + .title { + font-size: 1.1em; + } // the avatar icon is always small &.large {ul#banner_nav_ul li.tab.first {margin-left: $icon_small + $base_margin;}} diff --git a/app/stylesheets/ui/directory.scss b/app/stylesheets/ui/directory.scss index 262a7acfbf2b1bf43f12dff19eaca00512a6eb5d..0b5b3d11a04928388d8dd572929f34579a99f7a6 100644 --- a/app/stylesheets/ui/directory.scss +++ b/app/stylesheets/ui/directory.scss @@ -8,7 +8,7 @@ } .entry { - overflow: auto; // self-clear + overflow: hidden; // self-clear .avatar { float: left; diff --git a/app/views/common/items/_new_form.html.haml b/app/views/common/items/_new_form.html.haml index 644478f2814772d6711d4afab3109135f42f6025..528494471588a7a179c2b1f599abf26266762441 100644 --- a/app/views/common/items/_new_form.html.haml +++ b/app/views/common/items/_new_form.html.haml @@ -1,10 +1,12 @@ -- # expects the following locals: -- # item - a new active record element of the item to create -- # url - a url to submit the form to - +- # Expects the following locals: +- # item - a new active record element of the item to create +- # url - a url to submit the form to +- # You can also yield additional form elements. +- # for an example see +- # /extensions/pages/task_list_page/app/views/tasks/_new.html.haml :ruby type = dom_class(item) if type.blank? - label = I18n.t("#{type}.add") + label = I18n.t("actions.#{type}.add") .accordion-group[item] .accordion-heading[item, :link] @@ -18,8 +20,9 @@ rows: '4', class: "#{type}_description", placeholder: :details.t + = yield if block_given? %p - %button.btn.btn-primary + %button.btn.btn-primary{data: {"disable-with" => label}} = label = spinner diff --git a/app/views/common/pages/search/index.html.haml b/app/views/common/pages/search/index.html.haml index 1cc88877e63b300a9373966766c0659fa9d8d206..7283508ccc1630f14aa45326bb08affeb4637c25 100644 --- a/app/views/common/pages/search/index.html.haml +++ b/app/views/common/pages/search/index.html.haml @@ -1,5 +1,7 @@ - @local_layout = 'sidebar' -= render partial: 'common/pages/search/top_controls' +- content_for :title do + = render 'layouts/section/heading_with_info', section: :page_search += render 'common/pages/search/top_controls' #search_results{data: {search: 'path', href: page_search_path}} - if @path.present? diff --git a/app/views/layouts/context/_banner.html.haml b/app/views/layouts/context/_banner.html.haml index dc4667867850efac0c07a2ec1a5c5fdfae0b0659..ff1d2dc42962177800403b7aae9070fa02f71bc1 100644 --- a/app/views/layouts/context/_banner.html.haml +++ b/app/views/layouts/context/_banner.html.haml @@ -22,12 +22,9 @@ #context_banner can have one of three classes: large, medium, or small. This is used to determine the position of the first tab. -- if @context +- if visible_context? %header#context_banner.large.gap-under-masthead{class: (banner_picture ? 'dark_border' : 'light_border')} %div#banner_content - - if @context.entity.is_a?(Committee) or @context.entity.is_a?(Council) - = render partial: '/layouts/context/nested_banner_content' - - else - = render partial: '/layouts/context/normal_banner_content' + = render @context.banner_partial = render partial: '/layouts/context/nav/banner_menu' diff --git a/app/views/layouts/context/_hidden_banner_content.html.haml b/app/views/layouts/context/_hidden_banner_content.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..59748114cac67de0f4e63e477bf3ea255ec61ce8 --- /dev/null +++ b/app/views/layouts/context/_hidden_banner_content.html.haml @@ -0,0 +1,3 @@ +%a.avatar{style: square_avatar_style(nil, 'large')} +.title + =t :anonymous diff --git a/app/views/layouts/context/_normal_banner_content.html.haml b/app/views/layouts/context/_normal_banner_content.html.haml index 483cfb9f1fb96f353aca651210268bf6860941ab..bc2062bb8589378abcaabe80f33a55a6da53569a 100644 --- a/app/views/layouts/context/_normal_banner_content.html.haml +++ b/app/views/layouts/context/_normal_banner_content.html.haml @@ -5,7 +5,7 @@ .big_screen - if @context.avatar %a.avatar{href: entity_path(@context.entity), style: square_avatar_style(@context.entity, 'large')} - = link_to_banner_title(@context.entity, 'large') + = link_to_banner_title(@context.entity) .small_screen - if @context.avatar %a.avatar{href: entity_path(@context.entity), style: square_avatar_style(@context.entity, 'small')} diff --git a/app/views/layouts/global/_head.html.haml b/app/views/layouts/global/_head.html.haml index 66262a5c9702157e51dfaea52c945ba4a8edf7fe..1449dfeafbf0086a658aec8128536f82922d7f9e 100644 --- a/app/views/layouts/global/_head.html.haml +++ b/app/views/layouts/global/_head.html.haml @@ -10,6 +10,10 @@ = crabgrass_javascripts / end scripts = csrf_meta_tag +- if context_banner_style || @content_for_style + :css + #{@content_for_style} + #{context_banner_style} %title =h html_title =# call_hook :html_head diff --git a/app/views/layouts/global/nav/_boxes.html.haml b/app/views/layouts/global/nav/_boxes.html.haml index 22b3502d2698d867d854ad3c63744601c9150dd2..dadbfee55aa034e5b222b6fab73400c75a83b0f7 100644 --- a/app/views/layouts/global/nav/_boxes.html.haml +++ b/app/views/layouts/global/nav/_boxes.html.haml @@ -8,7 +8,7 @@ - if entities.present? %div{style:"display: none", class: columns[:right_col].empty? ? "menu_items" : "menu_items twocols" } - - cache current_language do + - cache [current_language, id] do .h3.first = heading %small diff --git a/app/views/layouts/section/README b/app/views/layouts/section/README new file mode 100644 index 0000000000000000000000000000000000000000..e8aff12e089a3ce998f3d2e643b0eb5dcffab4f1 --- /dev/null +++ b/app/views/layouts/section/README @@ -0,0 +1,4 @@ +Section Layouts +=============== + +These are reusable layouts for sections of the main content. diff --git a/app/views/layouts/section/_heading_with_info.html.haml b/app/views/layouts/section/_heading_with_info.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..77a97b779826ece24b1ca924a2c54baec4a03a90 --- /dev/null +++ b/app/views/layouts/section/_heading_with_info.html.haml @@ -0,0 +1,6 @@ +-# if there is only one section in your content you might want to +-# render this partial in the title (content_for :title do...) +%h2 + =t section, scope: :headings, cascade: true + %small + =t section, scope: "headings.info", default: "" diff --git a/app/views/me/notices/_notice.html.haml b/app/views/me/notices/_notice.html.haml index 41db6ca78cab87c8f72dfde5d24412f83d37d7df..a6fa0e378c0035f96f18440f0bce6921ecb41e8a 100644 --- a/app/views/me/notices/_notice.html.haml +++ b/app/views/me/notices/_notice.html.haml @@ -10,7 +10,7 @@ =h embold_links notice.display_title %br - if notice.display_body_as_quote? - %i= embold_links(notice.display_body) + %i= strip_tags(notice.display_body).truncate(300).html_safe - else = embold_links(notice.display_body) %td.nowrap.align_right.reflow diff --git a/app/views/me/notices/index.html.haml b/app/views/me/notices/index.html.haml index 2654ca51c59888c7ffc78079d4c4feb2a2e11535..cc94b90e117932b2ae87795a2c3a0db55733d580 100644 --- a/app/views/me/notices/index.html.haml +++ b/app/views/me/notices/index.html.haml @@ -8,5 +8,5 @@ = render partial: 'notice', collection: @notices = bottom_pagination_links @notices -.h2=:recent_pages.t += render 'layouts/section/heading_with_info', section: :recent_pages = render partial: 'common/pages/list', locals: {style: 'table'} diff --git a/app/views/pages/details/_information.html.haml b/app/views/pages/details/_information.html.haml index 9d1496bb171a28a1be1551d62de4e8811215a991..d1515df8f1063f41d439821c0a30db9888a42fcd 100644 --- a/app/views/pages/details/_information.html.haml +++ b/app/views/pages/details/_information.html.haml @@ -15,7 +15,8 @@ - r.label :updated.tcap - r.input link_to_user(@page.updated_by, avatar: 'tiny') - r.input friendly_time(@page.updated_at) - - f.row do |r| - - r.label :statistics.t - - r.input render(partial: 'stats') + - if current_site.tracking? + - f.row do |r| + - r.label :statistics.t + - r.input render(partial: 'stats') diff --git a/app/views/pages/details/_stats.html.haml b/app/views/pages/details/_stats.html.haml index 76b38d258a71855e62ace1200d069e4d9cd7d43c..7e12ae7ea1923dc5b1ec9fda78550ac2c6e51a0b 100644 --- a/app/views/pages/details/_stats.html.haml +++ b/app/views/pages/details/_stats.html.haml @@ -3,7 +3,7 @@ - edits = @page.edits_stats %table.styled{width:'100%'} %tr - %th= " ".html_safe + %th %th= I18n.t(:viewed).capitalize %th= I18n.t(:starred).capitalize %th= I18n.t(:edited).capitalize @@ -26,5 +26,5 @@ %td= I18n.t(:date_all_time) %td= views[3] %td= stars[3] - %td= " ".html_safe + %td diff --git a/app/views/pages/sidebar/_sidebar.html.haml b/app/views/pages/sidebar/_sidebar.html.haml index 5d8de8b939f89b3dd934076245bd52baa21bd60b..dc43782956834ce7682ba11f02c7c5ae147d5d91 100644 --- a/app/views/pages/sidebar/_sidebar.html.haml +++ b/app/views/pages/sidebar/_sidebar.html.haml @@ -8,9 +8,12 @@ =# history_line - else %ul.side_list.commands + = public_line + %ul.side_list.commands.rule = watch_line = star_line - - if (access_changing_commands = [share_line, notify_line, public_line].compact).any? + - access_changing_commands = [share_line, notify_line].compact + - if access_changing_commands.present? %ul.side_list.commands.rule = access_changing_commands.join.html_safe %ul.side_list.commands.rule diff --git a/app/views/session/_login_form.html.haml b/app/views/session/_login_form.html.haml index 46bc83d8a0059bfba1c28a7d70337784b0ffb9a7..fec8b6598bf5d002dea3d798904b3a83eab93cb9 100644 --- a/app/views/session/_login_form.html.haml +++ b/app/views/session/_login_form.html.haml @@ -9,7 +9,7 @@ .login_form = form_tag(login_path, id: "entry") do - cache current_language do - #cookie_warning.alert.alert-error{display: 'none'} + .cookie_warning.alert.alert-error{style: "display: none"} = :cookie_disabled_warning.t %div %label(for = 'login')= :login_name.t @@ -25,15 +25,3 @@ - if params[:redirect] = hidden_field_tag 'redirect', params[:redirect] = javascript_tag "Form.focusFirstElement('entry');" - --# TODO: move into javascript assets -:javascript - document.observe("dom:loaded", function() { - document.cookie = "are_cookies_enabled=1; expires=" + (new Date(Date.now() + 2000)).toGMTString(); - if (document.cookie.length == 0) { - $('cookie_warning').show(); - } else { - $('cookie_warning').hide(); - } - }); - diff --git a/app/views/wikis/wikis/_edit.html.haml b/app/views/wikis/wikis/_edit.html.haml index 84341824e8fe4569239928af724eff40f76d4dc0..3aab0cbc84289e9b24922487c41ca56698d356a7 100644 --- a/app/views/wikis/wikis/_edit.html.haml +++ b/app/views/wikis/wikis/_edit.html.haml @@ -18,15 +18,16 @@ = hidden_field_tag :section, section if section && section != :document - if @error_message .alert.alert-error= @error_message.to_s - = text_area_tag('wiki[body]', h(body), {rows: wiki_textarea_rows(body), class: 'full_width', id: dom_id(wiki, 'textarea')}) + = text_area_tag('wiki[body]', h(body), {rows: wiki_textarea_rows(body), class: 'full_width', id: dom_id(wiki, 'textarea'), tabindex: 1}) .right_buttons.p -# NOTE: there is an event listener on input.wiki_button = spinner(spinner_id) - = f.submit :cancel_button.t, name: 'cancel', class: 'btn wiki_button' + = f.submit :cancel_button.t, name: 'cancel', tabindex: 3, + class: 'btn wiki_button' - if @show_force_save_button - = f.submit :force_save_button.t, name: 'force_save', + = f.submit :force_save_button.t, name: 'force_save', tabindex: 2, class: 'btn btn-primary wiki_button' - else - = f.submit :save_button.t, name: 'save', + = f.submit :save_button.t, name: 'save', tabindex: 2, class: 'btn btn-primary wiki_button' - .float_left= formatting_reference_link + .float_left= formatting_reference_link(tabindex: 4) diff --git a/config/application.rb b/config/application.rb index 17d5ca685e8ada8e1e02921a4d1a55e429ff7c6e..dad79f872b9566455b6aae4fe413aa6eddf3ebdb 100644 --- a/config/application.rb +++ b/config/application.rb @@ -88,7 +88,7 @@ module Crabgrass ] # allow plugins in more places - [CRABGRASS_PLUGINS_DIRECTORY, MODS_DIRECTORY, PAGES_DIRECTORY, WIDGETS_DIRECTORY].each do |path| + [CRABGRASS_PLUGINS_DIRECTORY, MODS_DIRECTORY, PAGES_DIRECTORY].each do |path| config.paths['vendor/plugins'] << path end diff --git a/config/directories.rb b/config/directories.rb index 14bd66eb746def50926db96a5dbe7839cb65aac4..f385a9e375ecfc9135c1137a3edc92df82be82fe 100644 --- a/config/directories.rb +++ b/config/directories.rb @@ -18,7 +18,6 @@ dirs << EXTENSION_DIRECTORY = APP_ROOT + "extensions" dirs << THEMES_DIRECTORY = EXTENSION_DIRECTORY + "themes" dirs << SEARCH_FILTERS_DIRECTORY = EXTENSION_DIRECTORY + "search_filters" dirs << LOCALE_OVERRIDE_DIRECTORY = EXTENSION_DIRECTORY + "locales" -dirs << WIDGETS_DIRECTORY = EXTENSION_DIRECTORY + "widgets" # plugins diff --git a/config/locales/en/crud-and-forms.yml b/config/locales/en/crud-and-forms.yml index 035570aa7c160ed9f178da4e13f0c806c0643c13..4ec28af352b8b474ffc360338424700d3866ec5c 100644 --- a/config/locales/en/crud-and-forms.yml +++ b/config/locales/en/crud-and-forms.yml @@ -75,3 +75,8 @@ en: enter_name_of_group_or_person: "Enter the name of a group or person" enter_name_of_group: "Enter the name of a group" enter_name_of_person: "Enter the name of a person" + actions: + task: + add: "Add new Task" + possible: + add: "Add new Possibility" diff --git a/config/locales/en/headings.yml b/config/locales/en/headings.yml new file mode 100644 index 0000000000000000000000000000000000000000..9ce86e9dfea5776c831783c3a615884004c86ebd --- /dev/null +++ b/config/locales/en/headings.yml @@ -0,0 +1,8 @@ +en: + headings: + page_search: "Search for pages" + recent_pages: "Recent Pages" + info: + page_search: "Find all pages you have access to directly or via your groups" + recent_pages: "You contributed to these pages or they were shared with you" + diff --git a/config/locales/en/pages.yml b/config/locales/en/pages.yml index fd2602c1e43226fa2230eba799482369ed6c37d4..9d122abf98e92a4667f8d2ce3318290695ae9683 100644 --- a/config/locales/en/pages.yml +++ b/config/locales/en/pages.yml @@ -3,8 +3,6 @@ en: pages: "Pages" recent_pages: "Recent Pages" #group_pages: "Group Pages" - #search_input_caption: "Search for pages" - #search_description: "Search through all pages you have access to" #my_pages: "My Pages" #view_work_pages_option: "All My Work Pages" @@ -131,6 +129,9 @@ en: email_link_expires: "This link will expire in %{days} days." page_notice_title: '<user>%{from}</user> sent you page "%{page_title}"' page_notice_title_with_message: '<user>%{from}</user> sent you page "%{page_title}" with the message:' + page_updated: '<user>%{from}</user> updated the page "%{page_title}"' + page_update: "Page Update" + ##! page_notice_message: "%{user} notified you about this page on %{date}" ##! page_with_message: "with message" @@ -389,7 +390,6 @@ en: completed_tasks: 'completed tasks' no_pending_tasks: 'no pending tasks' no_completed_tasks: 'no completed tasks' - add_task: 'Add Task' assign_to: 'assign to' @@ -411,8 +411,6 @@ en: ranked_vote_instructions: "Drag and drop the items on the following list until they are in order from most preferred at the top to least preferred at the bottom. When you are done, press confirm to record your vote." - possible: - add: "Add new possibility" confirm_vote_button: "Confirm Vote" edit_my_vote_tab: "Edit my vote" diff --git a/extensions/pages/asset_page/app/controllers/asset_page_versions_controller.rb b/extensions/pages/asset_page/app/controllers/asset_page_versions_controller.rb index 38bb3a0197490b7ab87152facf0effb5a6c09955..19efc529d3ab80506d3d24831060e43032d8bd7e 100644 --- a/extensions/pages/asset_page/app/controllers/asset_page_versions_controller.rb +++ b/extensions/pages/asset_page/app/controllers/asset_page_versions_controller.rb @@ -10,6 +10,7 @@ class AssetPageVersionsController < Pages::BaseController def create @asset.generate_thumbnails + current_user.updated(@page) render :update do |page| page.replace_html 'preview_area', asset_link_with_preview(@asset) end @@ -18,6 +19,7 @@ class AssetPageVersionsController < Pages::BaseController def destroy asset_version = @asset.versions.find_by_version(params[:id]) asset_version.destroy + current_user.updated(@page) render(:update) do |page| page.hide "asset_#{asset_version.asset_id}_version_#{asset_version.version}" end diff --git a/extensions/pages/asset_page/app/helpers/asset_page_helper.rb b/extensions/pages/asset_page/app/helpers/asset_page_helper.rb index b111a304914948b75e8203bf572c80294d68a1fd..0993f5d64998bb2425c64bfd51c57a00e5dfc255 100644 --- a/extensions/pages/asset_page/app/helpers/asset_page_helper.rb +++ b/extensions/pages/asset_page/app/helpers/asset_page_helper.rb @@ -3,7 +3,7 @@ module AssetPageHelper def asset_link_with_preview(asset) thumbnail = asset.thumbnail(:large) if thumbnail.nil? - link_to( image_tag(asset.big_icon), asset.url ) + link_to( icon_for(asset), asset.url ) elsif !thumbnail.exists? load_preview_tag + javascript_tag(create_preview_javascript) else diff --git a/extensions/pages/asset_page/app/views/asset_page/_information.html.haml b/extensions/pages/asset_page/app/views/asset_page/_information.html.haml index ac9b66363ffdd44e8181bca0b5fc5604d414c4bc..f0c4a047bae49e8d1dd1dad805f0046710cac37d 100644 --- a/extensions/pages/asset_page/app/views/asset_page/_information.html.haml +++ b/extensions/pages/asset_page/app/views/asset_page/_information.html.haml @@ -1,6 +1,6 @@ .p = friendly_size(@asset.size) + "," - = I18n.t(@asset.format_description.to_sym, default: @asset.format_description) + = I18n.t(@asset.format_description.to_sym, default: @asset.format_description) - if @asset.ext = "(" + @asset.ext + ")" @@ -8,7 +8,13 @@ - if previews.any? %br = :preview.t + ':' - = previews.collect{|preview| link_to preview.name, preview.url}.join(', ').html_safe + = previews.collect{|p| link_to p.name, p.url}.join(', ').html_safe + + - formats = @asset.thumbnails.other_formats + - if formats.any? + %br + = :other_formats.t + ':' + = formats.collect{|f| link_to f.name, f.url}.join(', ').html_safe - if @page.updated_by .p diff --git a/extensions/pages/core_page/test/functional/discussion_page_controller_test.rb b/extensions/pages/core_page/test/functional/discussion_page_controller_test.rb index ac83d8ab839ad05180c54983c956202d70d70207..163a1e1156f93df484e658f4aa6e1737b98f7257 100644 --- a/extensions/pages/core_page/test/functional/discussion_page_controller_test.rb +++ b/extensions/pages/core_page/test/functional/discussion_page_controller_test.rb @@ -1,4 +1,4 @@ -require File.dirname(__FILE__) + '/../../../../../test/test_helper' +require 'test_helper' class DiscussionPageControllerTest < ActionController::TestCase fixtures :pages, :users, :user_participations diff --git a/extensions/pages/ranked_vote_page/app/controllers/ranked_vote_possibles_controller.rb b/extensions/pages/ranked_vote_page/app/controllers/ranked_vote_possibles_controller.rb index a0b80d41620f9ad0bcb24235b36ae9394280bd1f..c64d4b0f6e2654cb21041b77865140dd9b9f1a0e 100644 --- a/extensions/pages/ranked_vote_page/app/controllers/ranked_vote_possibles_controller.rb +++ b/extensions/pages/ranked_vote_page/app/controllers/ranked_vote_possibles_controller.rb @@ -10,6 +10,7 @@ class RankedVotePossiblesController < Pages::BaseController # <%= sortable_element 'sort_list_xxx', .... %> def sort @poll.vote(current_user, sort_params) + current_user.updated(@page) find_possibles rescue ActionController::ParameterMissing render nothing: true @@ -19,6 +20,7 @@ class RankedVotePossiblesController < Pages::BaseController @possible = @poll.possibles.create possible_params if @poll.valid? and @possible.valid? @page.unresolve + current_user.updated(@page) else @poll.possibles.delete(@possible) warning @possible unless @possible.valid? @@ -31,10 +33,12 @@ class RankedVotePossiblesController < Pages::BaseController def update @possible.update_attributes possible_params.permit(:description) + current_user.updated(@page) end def destroy @possible.destroy + current_user.updated(@page) render nothing: true end diff --git a/extensions/pages/ranked_vote_page/app/views/ranked_vote_possibles/_possible_show.html.erb b/extensions/pages/ranked_vote_page/app/views/ranked_vote_possibles/_possible_show.html.erb index 06bc09d32776e0a04f551b1e627983d14a08253c..9f44160118a4402ae1c45625ccc9b72b6b565a9b 100644 --- a/extensions/pages/ranked_vote_page/app/views/ranked_vote_possibles/_possible_show.html.erb +++ b/extensions/pages/ranked_vote_page/app/views/ranked_vote_possibles/_possible_show.html.erb @@ -19,6 +19,6 @@ edit_url = edit_ranked_vote_possible_url(possible, page_id: @page) <%= link_to I18n.t(:edit), edit_url, icon:'pencil', class: 'edit', remote: true, method: :get %> </div> <div class='indent possible_details' id="<%=details_id%>" style='display: none'> - <%= possible.description_html.to_s.html_safe %> + <%= possible.description_html %> </div> diff --git a/extensions/pages/ranked_vote_page/test/integration/ranked_vote_test.rb b/extensions/pages/ranked_vote_page/test/integration/ranked_vote_test.rb index 7d91d4bc78a0d628587296711c4341b190102288..27e417e4446c9197ff2b73e14282e29f7448a077 100644 --- a/extensions/pages/ranked_vote_page/test/integration/ranked_vote_test.rb +++ b/extensions/pages/ranked_vote_page/test/integration/ranked_vote_test.rb @@ -13,9 +13,7 @@ class RankedVoteTest < JavascriptIntegrationTest def test_initial_option assert_page_header - click_link 'Add new possibility' option, description = add_possibility - click_link 'Add new possibility' # close assert_no_content description click_link option assert_content description @@ -26,9 +24,7 @@ class RankedVoteTest < JavascriptIntegrationTest end def test_voting - click_link 'Add new possibility' option, description = add_possibility - click_link 'Add new possibility' # close assert_not_voted_yet vote assert_voted @@ -38,10 +34,8 @@ class RankedVoteTest < JavascriptIntegrationTest def test_multiple_options - click_link 'Add new possibility' add_possibility option, description = add_possibility - click_link 'Add new possibility' # close click_page_tab 'Show results' click_link option assert_content description diff --git a/extensions/pages/rate_many_page/app/controllers/rate_many_possibles_controller.rb b/extensions/pages/rate_many_page/app/controllers/rate_many_possibles_controller.rb index 97aea7b06b78b840e5d6556fb9481801cbc6937c..9c6fd0c254f04875ad25588046cfc717cc756790 100644 --- a/extensions/pages/rate_many_page/app/controllers/rate_many_possibles_controller.rb +++ b/extensions/pages/rate_many_page/app/controllers/rate_many_possibles_controller.rb @@ -20,7 +20,8 @@ class RateManyPossiblesController < Pages::BaseController def create @possible = @poll.possibles.create possible_params if @poll.valid? and @possible.valid? - @page.unresolve # update modified_at, auto_summary, and make page unresolved for other participants + current_user.updated(@page) + @page.unresolve else @poll.possibles.delete(@possible) flash_message_now object: @possible unless @possible.valid? @@ -33,9 +34,7 @@ class RateManyPossiblesController < Pages::BaseController return unless @poll possible = @poll.possibles.find(params[:id]) possible.destroy - - current_user.updated @page # update modified date, and auto_summary, but do not make it unresolved - + current_user.updated @page redirect_to page_url(@page, action: 'show') end diff --git a/extensions/pages/rate_many_page/test/integration/rate_many_page_test.rb b/extensions/pages/rate_many_page/test/integration/rate_many_page_test.rb index e978a58213bb15fd87caae59bffd49e6c4844dac..3392d396035e54c2e7e7ca84ebbf2c42ce5743ce 100644 --- a/extensions/pages/rate_many_page/test/integration/rate_many_page_test.rb +++ b/extensions/pages/rate_many_page/test/integration/rate_many_page_test.rb @@ -12,9 +12,7 @@ class RateManyPageTest < JavascriptIntegrationTest def test_initial_option assert_page_header - click_link 'Add new possibility' option, description = add_possibility - click_link 'Add new possibility' # close assert_content option assert_no_content description click_on option @@ -24,9 +22,7 @@ class RateManyPageTest < JavascriptIntegrationTest end def test_voting - click_link 'Add new possibility' option, description = add_possibility - click_link 'Add new possibility' # close choose 'good' within('.possibles') do assert_content @user.login diff --git a/extensions/pages/survey_page/app/controllers/survey_page_response_controller.rb b/extensions/pages/survey_page/app/controllers/survey_page_response_controller.rb index 79e62deb42cef509645fc7ac1635cea155fa757f..1959e1249328e7673b117c307ebffe2b1de1ad4b 100644 --- a/extensions/pages/survey_page/app/controllers/survey_page_response_controller.rb +++ b/extensions/pages/survey_page/app/controllers/survey_page_response_controller.rb @@ -6,7 +6,7 @@ class SurveyPageResponseController < Pages::BaseController helper 'survey_page' guard show: :may_view_survey_response?, - list: :may_view_survey_response?, + index: :may_view_survey_response?, update: :may_modify_survey_response?, edit: :may_modify_survey_response?, new: :may_create_survey_response?, @@ -17,6 +17,23 @@ class SurveyPageResponseController < Pages::BaseController before_filter :verify_post, only: [:make, :update, :destroy] + def show + @response = @survey.responses.find_by_id params[:id] + if params[:jump] + redirect_to response_path(get_jump_id, page_id: @page.id) + end + end + + def index + @responses = @survey.responses.paginate({ + include: ['answers', 'ratings'], + page: params[:page] + }) + end + +=begin + + def new @response = SurveyResponse.new end @@ -67,20 +84,6 @@ class SurveyPageResponseController < Pages::BaseController end end - def show - @response = @survey.responses.find_by_id params[:id] - if params[:jump] - redirect_to page_url(@page, controller: :response, action: :show, id: get_jump_id) - end - end - - def list - @responses = @survey.responses.paginate({ - include: ['answers', 'ratings'], - page: params[:page] - }) - end - # xhr and get # The user may either rate the current response, or skip it. The response # has either been rated already or not. If it has been rated already, it may @@ -119,6 +122,7 @@ class SurveyPageResponseController < Pages::BaseController end end +=end protected diff --git a/extensions/pages/survey_page/app/helpers/survey_page_helper.rb b/extensions/pages/survey_page/app/helpers/survey_page_helper.rb index 51995d76118470c13618f9732b2c3aa1fdf9a0d7..35c2d7200a692cea6b87a960a9d8b5503eb54c51 100644 --- a/extensions/pages/survey_page/app/helpers/survey_page_helper.rb +++ b/extensions/pages/survey_page/app/helpers/survey_page_helper.rb @@ -51,17 +51,10 @@ module SurveyPageHelper def show_answers_for_question(response, question) # filter answers for this response and ignore unchecked checkboxes - answers = @response.answers.select {|a| a.question == question && a.value != SurveyAnswer::CHOICE_FOR_UNCHECKED } - - tags = answers.collect do |answer| - if answer.asset - render_asset(answer.asset, answer.value) - else - content_tag(:div, answer.display_value, class: 'answer') - end + answers = @response.answers.select do |a| + a.question == question && a.value != SurveyAnswer::CHOICE_FOR_UNCHECKED end - - tags.join("\n") + render partial: 'survey_page_response/answer', collection: answers end def render_asset(asset, name) diff --git a/extensions/pages/survey_page/app/views/survey_page/_tabs.html.haml b/extensions/pages/survey_page/app/views/survey_page/_tabs.html.haml index 9d8db19b634f1b4e18e2b9d2e5a2d501d47b2231..e064f76695d95764590b72764933acc866142206 100644 --- a/extensions/pages/survey_page/app/views/survey_page/_tabs.html.haml +++ b/extensions/pages/survey_page/app/views/survey_page/_tabs.html.haml @@ -9,10 +9,10 @@ - if my_response and may_view_survey_response?(my_response) - f.tab do |t| - t.label :survey_my_response_tab.t - - t.url page_path(@page, controller: :response, action: :show, id: my_response.id) + - t.url response_path(my_response, page_id: @page) - t.selected controller?(:survey_page_response) && action?(:show, :edit) && id?(my_response.id) - if may_view_survey_response? - f.tab do |t| - t.label :survey_list_all_tab.t - - t.url page_path(@page, controller: :response, action: :list) + - t.url responses_path(page_id: @page) - t.selected controller?(:survey_page_response) && action?(:list, :edit, :show) && !id?(my_response) diff --git a/extensions/pages/survey_page/app/views/survey_page_response/_answer.html.haml b/extensions/pages/survey_page/app/views/survey_page_response/_answer.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..bde364754a674f51441a89cd177fe3b4115e4d9e --- /dev/null +++ b/extensions/pages/survey_page/app/views/survey_page_response/_answer.html.haml @@ -0,0 +1,4 @@ +- if answer.asset + = render_asset(answer.asset, answer.value) +- else + .answer= answer.display_value diff --git a/extensions/pages/survey_page/app/views/survey_page_response/_show_response.html.haml b/extensions/pages/survey_page/app/views/survey_page_response/_show_response.html.haml index cd0c5a070aea2a10274aeba9dc818a5f5edb2c44..1892fd5e7e141f0ad8fac2bc8ac88e1ee7ad13fc 100644 --- a/extensions/pages/survey_page/app/views/survey_page_response/_show_response.html.haml +++ b/extensions/pages/survey_page/app/views/survey_page_response/_show_response.html.haml @@ -17,4 +17,4 @@ %span • #{:private.t} %br/ - = show_answers_for_question(@response, question) \ No newline at end of file + = show_answers_for_question(@response, question) diff --git a/extensions/pages/survey_page/app/views/survey_page_response/list.html.haml b/extensions/pages/survey_page/app/views/survey_page_response/index.html.haml similarity index 77% rename from extensions/pages/survey_page/app/views/survey_page_response/list.html.haml rename to extensions/pages/survey_page/app/views/survey_page_response/index.html.haml index 073128f4f89a37ae267d4628450f5e6e5a025aac..ec4d54d934fb3c7f28d2bf528b7c9d7983bfafcf 100644 --- a/extensions/pages/survey_page/app/views/survey_page_response/list.html.haml +++ b/extensions/pages/survey_page/app/views/survey_page_response/index.html.haml @@ -1,4 +1,4 @@ -= pagination_links @responses, params: {controller: :response, action: :list} += pagination_links @responses %table#survey_answers.pretty %tr %th user @@ -7,7 +7,7 @@ - (questions=@survey.questions[0..0]).each do |question| %th= truncate(question.label) - @responses.each do |resp| - - url = page_url(@page, controller: :response, action: :show, id: resp.id) + - url = response_path(resp, page_id: @page) %tr{class: cycle("odd","even")} %td= resp.user.login if resp.user_id %td= friendly_date resp.created_at @@ -24,5 +24,5 @@ = link_to(:see_whole_response_link.t, url) - else \— -= pagination_links @responses, params: {controller: :response, action: :list} += pagination_links @responses %br/ diff --git a/extensions/pages/survey_page/app/views/survey_page_response/show.html.haml b/extensions/pages/survey_page/app/views/survey_page_response/show.html.haml index f29d80db824de294c93276e03f4398bed8f5de2a..340b64da47670800ffa0288f520e64fc0f3a0398 100644 --- a/extensions/pages/survey_page/app/views/survey_page_response/show.html.haml +++ b/extensions/pages/survey_page/app/views/survey_page_response/show.html.haml @@ -1,11 +1,10 @@ - links = [] - if @response - if @response.user_id != current_user.id - - links << link_to(:pagination_previous.t, page_url(@page, controller: :response, action: :show, id: @response.id, jump: 'prev')) - - links << link_to(:return_link.t, page_url(@page, controller: :response, action: :list)) - - links << link_to(:pagination_next.t, page_url(@page, controller: :response, action: :show, id: @response.id, jump: 'next')) -- if @response + - links << link_to(:pagination_previous.t, response_path(@response, page_id: @page, jump: 'prev')) + - links << link_to(:return_link.t, responses_path(page_id: @page) + - links << link_to(:pagination_next.t, response_path(@response.id, @page, jump: 'next')) = link_line(*links) = render partial: 'show_response' - else - = :no_search_results.t \ No newline at end of file + = :no_search_results.t diff --git a/extensions/pages/survey_page/init.rb b/extensions/pages/survey_page/init.rb index 1dd1bda2a69d1f2400cb26f7dd30749c63b8d167..ddb78f6d2931a61770c9323369a1dda08431d503 100644 --- a/extensions/pages/survey_page/init.rb +++ b/extensions/pages/survey_page/init.rb @@ -14,9 +14,14 @@ define_page_type :SurveyPage, { Crabgrass.mod_routes do scope path: 'pages' do resources :surveys, - only: [:show, :edit], + only: [:show], controller: :survey_page do -# get :print, on: :member + get :print, on: :member end end + + scope path: 'pages/:page_id' do + resources :responses, only: [:show, :index], + controller: :survey_page_response + end end diff --git a/extensions/pages/task_list_page/app/controllers/tasks_controller.rb b/extensions/pages/task_list_page/app/controllers/tasks_controller.rb index 14dcd86c8a1baa105afbf4efd7fb5b5b01737377..890890ce7f54a37fb498c083187db511f011db24 100644 --- a/extensions/pages/task_list_page/app/controllers/tasks_controller.rb +++ b/extensions/pages/task_list_page/app/controllers/tasks_controller.rb @@ -8,7 +8,9 @@ class TasksController < Pages::BaseController @task = Task.new task_params @task.name = 'untitled' if @task.name.blank? @task.task_list = @list - @task.save + if @task.save + current_user.updated(@page) + end end # ajax only, returns nothing @@ -50,12 +52,14 @@ class TasksController < Pages::BaseController locals: {task: @task} end end + current_user.updated(@page) end def destroy @task = @list.tasks.find(params[:id]) @task.remove_from_list @task.destroy + current_user.updated(@page) render nothing: true end diff --git a/extensions/pages/task_list_page/app/views/tasks/_inner_task_show.html.haml b/extensions/pages/task_list_page/app/views/tasks/_inner_task_show.html.haml index 245bcadf1bf553b59dafa90112566cd80bc95c56..57fb257259e5a9d4fce4e5a7b5a2e1a13be04d9b 100644 --- a/extensions/pages/task_list_page/app/views/tasks/_inner_task_show.html.haml +++ b/extensions/pages/task_list_page/app/views/tasks/_inner_task_show.html.haml @@ -6,7 +6,7 @@ .task{id: "#{dom_id(task,'details')}", style: "display:none"} %table %tr - %td{colspan: "2"}= task.description_html.to_s.html_safe + %td{colspan: "2"}= task.description_html %tr %td Created: #{friendly_date(task.created_at)} %td Completed: #{friendly_date(task.completed_at)} diff --git a/extensions/pages/task_list_page/app/views/tasks/_new.html.haml b/extensions/pages/task_list_page/app/views/tasks/_new.html.haml index baa29e536a7ce135ee90fc4fe502eba51df0491c..f1419eb2b3922da63ab59fadcd40b01ea0375893 100644 --- a/extensions/pages/task_list_page/app/views/tasks/_new.html.haml +++ b/extensions/pages/task_list_page/app/views/tasks/_new.html.haml @@ -1,27 +1,7 @@ -- # TODO: -- # you might want to consider using /items/_new_form and -- # including the extra fields there. - -- @task = Task.new -#new-task-link - = link_to_function :add_task.t, show('new-task') + hide('new-task-link') -#new-task{style: "display:none"} - = form_remote_tag( *options_for_new_task_form(page) ) do - %br/ - = text_field 'task', 'name', - class: 'task_name', - placeholder: :description.t - %br/ - = text_area 'task', 'description', - size: '50x4', - class: 'task_description', - placeholder: :details.t - %br/ - = :assign_to.t - %br/ - = checkboxes_for_assign_people_to_task(@task, [current_user.id], page) - %br{style: "clear:left"}/ - %p - = submit_tag :add_task.t - = button_to_function :done.t, hide('new-task') + show('new-task-link') - = spinner('new-task') +- locals = {item: Task.new, url: tasks_url(page_id: @page)} += render layout: 'common/items/new_form', locals: locals do + %br/ + = :assign_to.t + %br/ + = checkboxes_for_assign_people_to_task(@task, [current_user.id], page) + %br{style: "clear:left"}/ diff --git a/extensions/pages/task_list_page/test/integration/task_list_test.rb b/extensions/pages/task_list_page/test/integration/task_list_test.rb index d5141a359c57cb25eb6d06e74b6e3174eb05390f..211767e4bb5a328857af8e79090ffae177334989 100644 --- a/extensions/pages/task_list_page/test/integration/task_list_test.rb +++ b/extensions/pages/task_list_page/test/integration/task_list_test.rb @@ -14,16 +14,18 @@ class TaskListTest < JavascriptIntegrationTest assert_page_header assert_no_tasks add_task + add_task assert_tasks_pending assert_task_assigned_to(user) complete_task assert_tasks_completed + assert_tasks_pending end def test_assigning_task share_page_with users(:red) add_task - click_on 'Done' + close_task_form assign_task_to users(:red) unassign_task_from user assert_task_not_assigned_to users(:blue) @@ -31,12 +33,12 @@ class TaskListTest < JavascriptIntegrationTest end def add_task(options = {}) - click_on 'Add Task' if page.has_selector?(:link, 'Add Task') options[:description] ||= Faker::Lorem.sentence options[:detail] ||= Faker::Lorem.paragraph + open_task_form fill_in 'task_name', with: options[:description] fill_in 'task_description', with: options[:detail] - click_on "Add Task" + click_button "Add new Task" return options end @@ -65,6 +67,14 @@ class TaskListTest < JavascriptIntegrationTest end end + def open_task_form + click_link 'Add new Task' unless page.has_button? 'Add new Task' + end + + def close_task_form + click_link 'Add new Task' if page.has_button? 'Add new Task' + end + def complete_task within '#sort_list_pending' do find('.check_off_16').click diff --git a/extensions/pages/wiki_page/test/functional/wiki_page_controller_test.rb b/extensions/pages/wiki_page/test/functional/wiki_page_controller_test.rb index e0dc04aa6db3a987eb45de404e08d36df1068305..2a1dbd04a7bcdd7553c81ea5737bb6e472668be5 100644 --- a/extensions/pages/wiki_page/test/functional/wiki_page_controller_test.rb +++ b/extensions/pages/wiki_page/test/functional/wiki_page_controller_test.rb @@ -11,10 +11,10 @@ class WikiPageControllerTest < ActionController::TestCase assert_response :success end - def test_deny_show_without_login + def test_not_found_without_login # existing page get :show, id: pages(:wiki) - assert_login_required + assert_not_found end def test_show_without_login diff --git a/extensions/themes/default/navigation.rb b/extensions/themes/default/navigation.rb index 5b1d56ac24e0cc2fb1c193dcf176f4a83f150366..8a8d2b13f12330151a0ee2e53a6ea47793555f08 100644 --- a/extensions/themes/default/navigation.rb +++ b/extensions/themes/default/navigation.rb @@ -142,7 +142,7 @@ define_navigation do global_section :people do label { :people.t } url controller: 'people/directory' - active { controller?('people/') or context?(:user) } + active { controller?('people/') or (context?(:user) && visible_context?) } html partial: '/layouts/global/nav/people_menu' context_section :no_context do @@ -174,6 +174,7 @@ define_navigation do label { :home.t } icon :house url { entity_path(@user) } + visible { current_user.may?(:view, @user) } active { controller?('people/home') } end @@ -181,6 +182,7 @@ define_navigation do label { :pages.t } icon :page_white_copy url { person_pages_path(@user) } + visible { current_user.may?(:view, @user) } active { page_controller? } end @@ -193,7 +195,7 @@ define_navigation do global_section :group do label { :groups.t } url { groups_directory_path } - active { controller?('groups/') or context?(:group) } + active { controller?('groups/') or (context?(:group) && visible_context?) } html partial: '/layouts/global/nav/groups_menu' context_section :directory do diff --git a/lib/extends/active_record.rb b/lib/extends/active_record.rb index bc2682e9ef38cfe8b7275dbed3304de946666cd5..536a10af2328de66862b986f4ffdf915cc29d216 100644 --- a/lib/extends/active_record.rb +++ b/lib/extends/active_record.rb @@ -25,7 +25,8 @@ ActiveRecord::Base.class_eval do # # format_attribute :description # - # Will save an html copy in description_html. This other column must exist + # Will save an html copy in description_html. This other column must exist. + # The other column will return html_safe values. # # format_attribute :summary, :options => [:lite_mode] # @@ -34,20 +35,23 @@ ActiveRecord::Base.class_eval do def self.format_attribute(attr_name, flags={}) flags[:options] ||= [] #class << self; include ActionView::Helpers::TagHelper, ActionView::Helpers::TextHelper, WhiteListHelper; end - define_method(:body) { read_attribute attr_name } - define_method(:body_html) { read_attribute "#{attr_name}_html" } - define_method(:body_html=) { |value| write_attribute "#{attr_name}_html", value } - before_save :format_body - define_method(:format_body) { - if body.present? and (body_html.empty? or (send("#{attr_name}_changed?") and !send("#{attr_name}_html_changed?"))) - body.strip! - if respond_to?('owner_name') - self.body_html = GreenCloth.new(body, owner_name, flags[:options]).to_html - else - self.body_html = GreenCloth.new(body, 'page', flags[:options]).to_html - end - end + define_method("#{attr_name}_html") { + super().try.html_safe } + before_save :"format_#{attr_name}" + define_method("format_#{attr_name}") { + return unless formatted_attribute_needs_update?(attr_name) + plain = send("#{attr_name}").strip + context = respond_to?('owner_name') ? owner_name : 'page' + value = GreenCloth.new(plain, context, flags[:options]).to_html + send("#{attr_name}_html=", value) + } + end + + def formatted_attribute_needs_update?(attr_name) + return false if send("#{attr_name}").blank? + return true if send("#{attr_name}_html").blank? + send("#{attr_name}_changed?") && !send("#{attr_name}_html_changed?") end # used to give a default value to serializable attributes diff --git a/test/functional/assets_controller_test.rb b/test/functional/assets_controller_test.rb index c3c250be03b4db491f583fcb6ed7c8f7ee719b28..9f30b2f6206dd782f701ffad3385885fdc70a5c0 100644 --- a/test/functional/assets_controller_test.rb +++ b/test/functional/assets_controller_test.rb @@ -5,7 +5,7 @@ class AssetsControllerTest < ActionController::TestCase def test_get_permissions ImageAsset.any_instance.stubs(:public?).returns(false) asset = FactoryGirl.create :image_asset - get :show, id: asset.id, path: asset.filename + get :show, id: asset.id, path: asset.basename assert_login_required end @@ -14,9 +14,9 @@ class AssetsControllerTest < ActionController::TestCase asset = FactoryGirl.create :image_asset @controller.stubs(:authorized?).returns(true) @controller.expects(:private_filename).returns(asset.private_filename) - get :show, id: asset.id, path: asset.filename + get :show, id: asset.id, path: asset.basename @controller.expects(:private_filename).returns(thumbnail(asset.private_filename)) - get :show, id: asset.id, path: thumbnail(asset.filename) + get :show, id: asset.id, path: thumbnail(asset.basename) end def test_destroy @@ -34,7 +34,8 @@ class AssetsControllerTest < ActionController::TestCase private def thumbnail(path) - path.sub('.jpg', '_small.jpg') + ext = File.extname(path) + path.sub(/#{ext}$/, "_small#{ext}") end end diff --git a/test/functional/me/destroys_controller_test.rb b/test/functional/me/destroys_controller_test.rb index 9bb5eab798fb2ccb90e06a12789bef2c7983a026..f74d35e923f07ee0cf697f169eaaf296e32b6251 100644 --- a/test/functional/me/destroys_controller_test.rb +++ b/test/functional/me/destroys_controller_test.rb @@ -11,12 +11,12 @@ class Me::DestroysControllerTest < ActionController::TestCase assert_login_required end - # following tests fail as updating of type in ghostify! doesn't now work in testing environment. def test_update login_as @user post :update assert_equal @user.display_name, @user.reload.display_name assert_nil @user.reload.crypted_password + assert_equal [], @user.keys end def test_update_scrub_name diff --git a/test/functional/pages/participations_controller_test.rb b/test/functional/pages/participations_controller_test.rb new file mode 100644 index 0000000000000000000000000000000000000000..e0d7ffb22fc8d1b7298c47516adc43e6f24aaa58 --- /dev/null +++ b/test/functional/pages/participations_controller_test.rb @@ -0,0 +1,28 @@ +require 'test_helper' + +class Pages::ParticipationsControllerTest < ActionController::TestCase + + def setup + @user = FactoryGirl.create :user + @page = FactoryGirl.create(:page) + @upart = @page.add(@user, access: :view) + @upart.save + login_as @user + end + + def test_star + post :update, page_id: @page, id: @upart, star: true + assert @upart.reload.star + end + + def test_watch + post :update, page_id: @page, id: @upart, watch: true + assert @upart.reload.watch + end + + def test_prevent_increasing_access + post :update, page_id: @page, id: @upart, access: :admin + assert_equal :view, @upart.reload.access_sym + end +end + diff --git a/test/functional/pages/posts_controller_test.rb b/test/functional/pages/posts_controller_test.rb index 974588c2eecaafb6d825e25c28cdb3194b90a19f..c16d20df03575b241d90fae85d64d11919be5bb3 100644 --- a/test/functional/pages/posts_controller_test.rb +++ b/test/functional/pages/posts_controller_test.rb @@ -1,4 +1,4 @@ -require_relative '../../test_helper' +require 'test_helper' class Pages::PostsControllerTest < ActionController::TestCase @@ -9,14 +9,10 @@ class Pages::PostsControllerTest < ActionController::TestCase def test_create_post login_as @user - body = "Test Message" xhr :post, :create, page_id: @page.id, post: { body: body } - assert_response :success - assert_equal 1, @page.reload.posts.count - assert_equal body, @page.posts.first.body - assert_equal @user, @page.updated_by + assert_successfully_posted_to @page end def test_edit_post @@ -26,4 +22,29 @@ class Pages::PostsControllerTest < ActionController::TestCase assert_response :success assert_equal @post, assigns[:post] end + + def test_post_on_public_page + public_page = FactoryGirl.create(:page, public: true) + login_as @user + xhr :post, :create, page_id: public_page, post: { + body: body + } + assert_successfully_posted_to public_page + # let's make sure posting a comment does not grant more access... + assert_nil public_page.user_participations.where(user_id: @user).first.access + # despite commenting you can only view the page because it is public + @user.clear_access_cache + assert !@user.may?(:view, public_page) + end + + def assert_successfully_posted_to(page) + assert_response :success + assert_equal 1, page.reload.posts.count + assert_equal body, page.posts.first.body + assert_equal @user, page.updated_by + end + + def body + "Test Message" + end end diff --git a/test/helpers/functional_test_helper.rb b/test/helpers/functional_test_helper.rb index 34fbfe16755fe79191fd8afdca303053fe1b84c9..ee0b4dc189f3fff9a76b8f9afeff4246e755d0d7 100644 --- a/test/helpers/functional_test_helper.rb +++ b/test/helpers/functional_test_helper.rb @@ -17,6 +17,10 @@ module FunctionalTestHelper assert_redirected_to root_path(redirect: @request.path) end + def assert_not_found + assert_response :not_found + end + # can pass either a regexp of the flash error string, # or the error symbol def assert_error_message(arg=nil) diff --git a/test/helpers/integration/javascript/page_actions.rb b/test/helpers/integration/javascript/page_actions.rb index 8d6e2fc02de1d065556969ae3641c0ba859d5d89..9231659d973fdae93ac3e773cfd5d42c6b12ed6b 100644 --- a/test/helpers/integration/javascript/page_actions.rb +++ b/test/helpers/integration/javascript/page_actions.rb @@ -35,6 +35,14 @@ module PageActions click_on 'Remove Star (1)' end + def watch_page + click_on 'Watch For Updates' + end + + def unwatch_page + click_on 'Watch For Updates' + end + def change_access_to(permission) click_on 'Page Details' find('a', text: 'Permissions').click diff --git a/test/helpers/integration/page_assertions.rb b/test/helpers/integration/page_assertions.rb index 5d2cc5a00f85508ffd8c14845ce8c2cb48e5f66e..7dd7fbf25e1dfd873ffdf1f8df403cac0ae85974 100644 --- a/test/helpers/integration/page_assertions.rb +++ b/test/helpers/integration/page_assertions.rb @@ -28,4 +28,13 @@ module PageAssertions def assert_page_not_starred assert_selector '#star.star_empty_dark_16' end + + def assert_page_watched + assert_selector '#watch_checkbox.check_on_16' + end + + def assert_page_not_watched + assert_selector '#watch_checkbox.check_off_16' + end + end diff --git a/test/helpers/integration/page_records.rb b/test/helpers/integration/page_records.rb index 49e16c0cb8d47eea744fd25a5e683c5ab4588cca..af89b58eab3a7659243ccfc00bca21e64b4a0bdf 100644 --- a/test/helpers/integration/page_records.rb +++ b/test/helpers/integration/page_records.rb @@ -4,12 +4,12 @@ module PageRecords options, type = type, nil if type.is_a? Hash options.merge! created_by: user page = new_page(type, options) - if page.new_record? - page.save - # ensure after_commit callbacks are triggered so sphinx indexes the page. - page.page_terms.committed! - end - page + save_and_index(page) + end + + def public_page + page = new_page public: true + save_and_index(page) end def with_page(types) @@ -20,7 +20,7 @@ module PageRecords def new_page(type=nil, options = {}) options, type = type, nil if type.is_a? Hash - page_options = options.slice :title, :summary, :created_by, :owner, :flow + page_options = options.slice :title, :summary, :created_by, :owner, :flow, :public page_options.merge! created_at: Time.now, updated_at: Time.now if type @page = records[type] ||= FactoryGirl.build(type, page_options) @@ -54,4 +54,13 @@ module PageRecords # workaround for having the right page title in the test record new_page.title = file.basename(file.extname) if type == :asset_page end + + def save_and_index(page) + if page.new_record? + page.save + # ensure after_commit callbacks are triggered so sphinx indexes the page. + page.page_terms.committed! + end + page + end end diff --git a/test/helpers/integration/possibility.rb b/test/helpers/integration/possibility.rb index 5e2b734a3eb498aab3e71d3ff0ef7f037abb0244..279c7213e0b2f03d72c8467b9b2f514db3272fb7 100644 --- a/test/helpers/integration/possibility.rb +++ b/test/helpers/integration/possibility.rb @@ -1,13 +1,23 @@ module Integration module Possibility + def open_new_possibility_form + click_link 'Add new Possibility' unless page.has_button? 'Add new Possibility' + end + + def close_new_possibility_form + click_link 'Add new Possibility' if page.has_button? 'Add new Possibility' + end + def add_possibility(description = nil, detail = nil) + open_new_possibility_form description ||= Faker::Lorem.sentence detail ||= Faker::Lorem.paragraph fill_in 'possible_name', with: description fill_in 'possible_description', with: detail - click_button "Add new possibility" + click_button "Add new Possibility" assert_text description + close_new_possibility_form return description, detail end end diff --git a/test/integration/page_access_test.rb b/test/integration/page_access_test.rb new file mode 100644 index 0000000000000000000000000000000000000000..973a7c5e54b70ab86360a5d6d05a695ef14724ab --- /dev/null +++ b/test/integration/page_access_test.rb @@ -0,0 +1,22 @@ +require 'javascript_integration_test' + +class PageAccessTest < JavascriptIntegrationTest + + def test_loosing_access + page = public_page + login + visit_page(page) + assert page.public? + assert_content page.title + watch_page + assert_page_watched + page.public = false + page.save + visit_page(page) + assert_content 'Not Found' + end + + def visit_page(page) + visit "/pages/#{page.name_url}" + end +end diff --git a/test/integration/page_sidebar_test.rb b/test/integration/page_sidebar_test.rb index 8184254b4a98ce554e47a4a8f4c59d4026832d24..46031f183d7e02f9309208357ab3eb0b66949cbd 100644 --- a/test/integration/page_sidebar_test.rb +++ b/test/integration/page_sidebar_test.rb @@ -59,6 +59,13 @@ class PageSidebarTest < JavascriptIntegrationTest assert_page_not_starred end + def test_watch + watch_page + assert_page_watched + unwatch_page + assert_page_not_watched + end + # regression test for #7834 def test_sharing_preserves_stars star_page diff --git a/test/integration/page_test.rb b/test/integration/page_test.rb index 2fa9eecaea2803c356a1b81cab173ca3f828e709..989ddea2e95255904d9dbbc099f68a2f4bab59c5 100644 --- a/test/integration/page_test.rb +++ b/test/integration/page_test.rb @@ -20,7 +20,8 @@ class PageTest < IntegrationTest visit "/#{page.owner_name}/#{page.name_url}" assert_equal other_user, page.reload.owner assert !page.public? - assert_content "Permission Denied" + assert_content "Not Found" + assert_no_content other_user.display_name end end end diff --git a/test/unit/pages/page_access_test.rb b/test/unit/pages/page_access_test.rb index ae22489f4dc42eb2736b26261127d60bffb5d906..240e74b3a1b02cbe9873de3361125839add01675 100644 --- a/test/unit/pages/page_access_test.rb +++ b/test/unit/pages/page_access_test.rb @@ -14,7 +14,7 @@ class PageAccessTest < ActiveSupport::TestCase page = create_page title: 'private page' assert !user.may?(:view, page), 'user should NOT be able to view page' - page.add(group) + page.add(group, access: :view) assert !user.may?(:view, page), 'we cache may? queries' user.clear_access_cache assert user.may?(:view, page), 'user should BE able to view page' diff --git a/test/unit/unauthenticated_user_test.rb b/test/unit/unauthenticated_user_test.rb index def7cc652bde15f8eebaa8c6fdeaa07561ba973c..225732f9548e3829ce453b1e059367774fed27c9 100644 --- a/test/unit/unauthenticated_user_test.rb +++ b/test/unit/unauthenticated_user_test.rb @@ -6,12 +6,10 @@ class UnauthenticatedUserTest < ActiveSupport::TestCase @user = UnauthenticatedUser.new end - def test_should_be_able_to_view_public_page - assert @user.may?(:view, Page.new(public: true)) - end - + # User.may? checks for access through participations. + # If the page is public should be checked separately def test_should_not_be_able_to_view_public_page - assert !@user.may?(:view, Page.new(public: false)) + assert !@user.may?(:view, Page.new(public: true)) end def test_method_missing_raises_permission_denied diff --git a/test/unit/user_ghost_test.rb b/test/unit/user_ghost_test.rb new file mode 100644 index 0000000000000000000000000000000000000000..f2d4d12797ee4e36554b08553f4f0e75992ac05e --- /dev/null +++ b/test/unit/user_ghost_test.rb @@ -0,0 +1,25 @@ +require 'test_helper' + +class UserGhostTest < ActiveSupport::TestCase + fixtures :users + + # + # Ghosts do not require a login or a password + # + def test_valid_without_attributes + assert UserGhost.new.valid? + end + + def test_retire_user + user = users(:blue) + user = user.ghostify! + user.retire! + user.reload + user.attributes.except("id", "type", "login", "display_name").each do |k, v| + assert_nil v, "expected #{k} to be cleared" + end + assert_equal "Blue!", user.display_name + assert_equal "blue", user.name + assert_equal [], user.keys + end +end diff --git a/vendor/gems/riseuplabs-greencloth-0.1/lib/green_tree.rb b/vendor/gems/riseuplabs-greencloth-0.1/lib/green_tree.rb index cfcec35d981fe823855be7b6e68236ba77f5c718..1c95aa786ce993f3aca0118e25a3e43bb9af2272 100644 --- a/vendor/gems/riseuplabs-greencloth-0.1/lib/green_tree.rb +++ b/vendor/gems/riseuplabs-greencloth-0.1/lib/green_tree.rb @@ -193,12 +193,14 @@ class GreenTree < Array # modifies markup # finds the location for each heading in the markup - def prepare_markup_start_index!(markup) + def prepare_markup_start_index!(markup, offset = 0) # recurse over children first, this way we're guaranteed # to find every occurance of any title text in left-to-right (or top-to-bottom in a greencloth text) # order + # children have a higher offset, let's keep it separate from our own. + child_offset = offset children.each do |node| - node.prepare_markup_start_index!(markup) + child_offset = node.prepare_markup_start_index!(markup, child_offset) end # assume the node markup starts at the begining of the document @@ -208,15 +210,16 @@ class GreenTree < Array if self.text # find the first occurance of this node in the markup - self.start_index = markup.index(self.markup_regexp) + self.start_index = markup.index(self.markup_regexp, offset) if self.start_index.nil? - raise GreenClothException, "GREENCLOTH ERROR: Can't find heading with text: '#{text}' in markup" + raise GreenClothException, "GREENCLOTH ERROR: Can't find heading with text: '#{text}' in markup '#{markup}' with regexp: '#{markup_regexp}'" else # modify the markup, so that it will no longer match # the markup_regexp at this position markup[self.start_index] = "\000" end end + return self.start_index end def prepare_markup_end_index!(markup) @@ -244,24 +247,23 @@ class GreenTree < Array # take out carriage returns heading_text = Regexp.escape(self.text.gsub(/\r\n/, "\n")) + # look for the words - but allow special chars in between + heading_text = heading_text.gsub(/\\\s/, '[\W_](.*[\W_])?') # remove html entities, and let them match one to several characters heading_text.gsub!(/&(\w{2,6}?|\\#[0-9A-Fa-f]{2,6});/,'.{1,3}') # add back carriage returns as optional heading_text.gsub!('\\n', '\\r?\\n') - # allowed formatting characters around heading text - # /[\.\[\]\^\s_\*\+\?\-~]/ Regexp.union( /^ - [ \.\[\]\^@_\*\+\?\-~]* - #{heading_text}[\.\[\]\^@\s_\*\+\?\-~]* - \s*\r?\n[=-]+\s*?(\r?\n\r?\n?|$) + [^\n]*#{heading_text}[^\n]*\s* + \n[=-]+\s*?(\r?\n\r?\n?|$) /x, /^ h#{heading_level}\.\s+ - [\.\[\]\^@\s_\*\+\?\-~]*#{heading_text}[\.\[\]\^@\s_\*\+\?\-~]* + [^\n]*#{heading_text}[^\n]* \s*?(\r?\n\r?\n?|$) /x ) diff --git a/vendor/gems/riseuplabs-greencloth-0.1/lib/greencloth.rb b/vendor/gems/riseuplabs-greencloth-0.1/lib/greencloth.rb index 7ff3a79d953a0a3fb57ea199c48a7f2cbf48781e..6f37cc1a7da7e1047078006f9378d34d8b5d97ed 100644 --- a/vendor/gems/riseuplabs-greencloth-0.1/lib/greencloth.rb +++ b/vendor/gems/riseuplabs-greencloth-0.1/lib/greencloth.rb @@ -455,7 +455,7 @@ class GreenCloth < RedCloth::TextileDoc # ^^^ get ride of leading returns. This makes it so the text in # <pre> doesn't appear in the browser with an empty first line. offtag = offtag_it(body) - if tag == '<pre>' or (leading_character.present? and leading_character!="\n") + if tag == '<pre>' or (leading_character && leading_character.strip != '') "#{tag}#{offtag}#{tag.sub('<','</')}" else "<pre><code>#{offtag}</code></pre>" @@ -728,7 +728,7 @@ class GreenCloth < RedCloth::TextileDoc text.gsub!(LONG_WORDS_RE) do |word| chopped = word.scan(/.{#{LONG_WORD_CHAR_MAX}}/) offtag = offtag_it("<wbr/><span class='break'> </span>") - remainder = word.split(/.{#{LONG_WORD_CHAR_MAX}}/).select{|str| str.present?} + remainder = word.split(/.{#{LONG_WORD_CHAR_MAX}}/).select{|str| str && str.strip != ''} (chopped + remainder).join(offtag) end end diff --git a/vendor/gems/riseuplabs-greencloth-0.1/lib/greencloth_structure.rb b/vendor/gems/riseuplabs-greencloth-0.1/lib/greencloth_structure.rb index 3ae771bd27388d0c7227a6a2e893dec8bb9d61d9..fc4e51e624d52a4610dfcda64425261dcd92dffb 100644 --- a/vendor/gems/riseuplabs-greencloth-0.1/lib/greencloth_structure.rb +++ b/vendor/gems/riseuplabs-greencloth-0.1/lib/greencloth_structure.rb @@ -16,22 +16,11 @@ module GreenclothStructure # but be warned that to_html will mangled the string and it will not the # original! def green_tree - begin - unless @green_tree - extract_headings - @green_tree = convert_to_tree(@headings) - else - @green_tree - end - rescue GreenClothException => exc - logger.error exc.message if defined? logger and logger.respond_to? :error - return GreenTree.from_hash({ - :children => [], - :name => nil, - :start_index => 0, - :end_index => self.size - 1, - :heading_level => 0}, - self) + unless @green_tree + extract_headings + @green_tree = convert_to_tree(@headings) + else + @green_tree end end @@ -40,7 +29,8 @@ module GreenclothStructure # called by the formatter whenever it encounters h1..h4 tags def add_heading(indent,text) text = extract_offtags(text.dup) - formatter.clean_html(text, {}) # strip ALL markup, modifies variable text. + # strip ALL markup, modifies variable text. + formatter.clean_html(text, {}) @headings ||= [] @heading_names ||= {} if text diff --git a/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/autolinks.yml b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/autolinks.yml new file mode 100644 index 0000000000000000000000000000000000000000..afd594f4d77683b76a6f1124066da76178049c2b --- /dev/null +++ b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/autolinks.yml @@ -0,0 +1,46 @@ +--- +in: http://riseup.net/-dashes/in/the/link- +out: <p><a href="http://riseup.net/-dashes/in/the/link-">riseup.net/-dashes/in/the/link-</a></p> +--- +in: "http://riseup.net/__weirdchar/in/the/link__" +out: <p><a href="http://riseup.net/__weirdchar/in/the/link__">riseup.net/__weirdchar/in/the/link__</a></p> +--- +in: http://riseup.net/!weirdchar/in/the/link!x +out: <p><a href="http://riseup.net/!weirdchar/in/the/link!x">riseup.net/!weirdchar/in/the/link!x</a></p> +--- +in: "*http://google.com/*" +out: <p><strong><a href="http://google.com/">google.com</a></strong></p> +--- +in: "_http://google.com/_" +out: <p><em><a href="http://google.com/">google.com</a></em></p> +--- +in: url with period https://riseup.net/?path/. +out: |- + <p>url with period <a href="https://riseup.net/?path/">riseup.net/?path</a>.</p> +--- +in: url with question mark https://riseup.net/path/? +out: |- + <p>url with question mark <a href="https://riseup.net/path/">riseup.net/path</a>?</p> +--- +in: url with query https://riseup.net/path/?page=20. +out: |- + <p>url with query <a href="https://riseup.net/path/?page=20">riseup.net/path/?page=20</a>.</p> +--- +in: http://riseup.net http://riseup.net +out: "<p><a href=\"http://riseup.net\">riseup.net</a> <a href=\"http://riseup.net\">riseup.net</a></p>" +--- +in: |- + <pre> + @@[http://riseup.net] + </pre> +out: |- + <pre>@@[http://riseup.net] + </pre> +--- +in: "http://www.sympa.org/wiki/manual/web-interface#wwsympa.conf_parameters" +out: "<p><a href=\"http://www.sympa.org/wiki/manual/web-interface#wwsympa.conf_parameters\">www.sympa.org/wiki/manual/web-interface...</a></p>" +--- +in: download ftp://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.27.tar.bz2 +out: |- + <p>download <a href="ftp://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.27.tar.bz2">www.kernel.org/pub/linux/kernel/v2.6/li...</a></p> + diff --git a/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/basic.yml b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/basic.yml new file mode 100644 index 0000000000000000000000000000000000000000..1d2b0a4f5e357c014f3bdc4b6d2f301790317698 --- /dev/null +++ b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/basic.yml @@ -0,0 +1,541 @@ +--- +name: headers +in: "header one\n=====\nheader two\n----" +out: "<h1 class=\"first\">header one</h1>\n<h2>header two</h2>" +--- +name: headers +in: "la la la\n\nheader one\n=====\nheader two\n----\nla la la" +out: "<p>la la la</p>\n<h1 class=\"first\">header one</h1>\n<h2>header two</h2>\n<p>la la la</p>" +--- +name: paragraphs +desc: Textile looks for paragraphs in your text. Paragraphs are separated by one blank line. Every paragraph is translated as an HTML paragraph. +in: |- + A single paragraph. + + Followed by another. +out: |- + <p>A single paragraph.</p> + <p>Followed by another.</p> +--- +name: block containing block start +in: |- + I saw a ship. It ate my elephant. +out: |- + <p>I saw a ship. It ate my elephant.</p> +--- +name: extended block containing block start +in: |- + p.. I saw a ship. It ate my elephant. + + When the elephant comes to take a p. you... +out: |- + <p>I saw a ship. It ate my elephant.</p> + <p>When the elephant comes to take a p. you…</p> +--- +name: blockquote containing block start +in: |- + bq. I saw a ship. It ate my elephant. +out: |- + <blockquote> + <p>I saw a ship. It ate my elephant.</p> + </blockquote> +--- +name: extended blockquote containing block start +in: |- + bq.. I saw a ship. It ate my elephant. + + When the elephant comes to take a p. you... +out: |- + <blockquote> + <p>I saw a ship. It ate my elephant.</p> + <p>When the elephant comes to take a p. you…</p> + </blockquote> +--- +name: notextile block containing block start +in: |- + notextile. I saw a ship. It ate my elephant. +out: |- + I saw a ship. It ate my elephant. +valid_out: false +--- +name: extended notextile block containing block start +in: |- + notextile.. I saw a ship. It ate my elephant. + + When the elephant comes to take a p. you... +out: |- + I saw a ship. It ate my elephant. + + When the elephant comes to take a p. you... +valid_out: false +--- +name: pre block containing block start +in: |- + pre. I saw a ship. It ate my elephant. +out: |- + <pre>I saw a ship. It ate my elephant.</pre> +--- +name: extended pre block containing block start +in: |- + pre.. I saw a ship. It ate my elephant. + + When the elephant comes to take a p. you... +out: |- + <pre>I saw a ship. It ate my elephant.</pre> + + <pre>When the elephant comes to take a p. you…</pre> + --- +name: html tags +desc: You can certainly use HTML tags inside your Textile documents. HTML will only be escaped if it’s found in a <code>pre</code> or <code>code</code> block. +in: |- + I am very serious. + + <pre> + I am very serious. + </pre> +out: |- + <p>I am very serious.</p> + + <pre> I am very serious. + </pre> +--- +name: line breaks +desc: Line breaks are converted to HTML breaks. +in: |- + I spoke. + And none replied. +out: |- + <p>I spoke.<br /> + And none replied.</p> +html_no_breaks: |- + <p>I spoke. + And none replied.</p> +lite_mode_out: |- + I spoke.<br /> + And none replied. +--- +name: curly quotes +desc: Single- and double-quotes around words or phrases are converted to curly quotations, much easier on the eye. +in: "\"Observe!\"" +out: <p>“Observe!”</p> +--- +name: double hyphens +desc: Double hyphens are replaced with an em-dash. +in: Observe--very nice! +out: <p>Observe—very nice!</p> +latex: "Observe---very nice!\n\n" +--- +name: double hyphens with spaces +desc: Double hyphens are replaced with an em-dash and surrounding spaces are preserved. +in: Observe -- very nice! +out: <p>Observe — very nice!</p> +latex: "Observe --- very nice!\n\n" +--- +name: parenthetical phrase set off with em dashes +desc: Sentences with two em dashes should not turn them into strikethroughs +in: An emdash indicates a parenthetical thought--like this one--which is set apart from the rest of a sentence. +out: "<p>An emdash indicates a parenthetical thought—like this one—which is set apart from the rest of a sentence.</p>" +latex: "An emdash indicates a parenthetical thought---like this one---which is set apart from the rest of a sentence.\n\n" +--- +name: parenthetical phrase set off with em dashes surrounded by spaces +desc: Sentences with two em dashes should not turn them into strikethroughs +in: An emdash indicates a parenthetical thought -- like this one -- which is set apart from the rest of a sentence. +out: "<p>An emdash indicates a parenthetical thought — like this one — which is set apart from the rest of a sentence.</p>" +latex: "An emdash indicates a parenthetical thought --- like this one --- which is set apart from the rest of a sentence.\n\n" +--- +name: single hyphens with spaces +desc: Single hyphens are replaced with en-dashes if they are surrounded by spaces. +in: Observe - tiny and brief. +out: <p>Observe – tiny and brief.</p> +latex: "Observe--tiny and brief.\n\n" +--- +name: midword hyphens +desc: Single hyphens are left alone if not surrounded by spaces. +in: Observe the nicely-done hyphen. +out: <p>Observe the nicely-done hyphen.</p> +--- +name: ellipses +desc: Triplets of periods become an ellipsis. +in: Observe... +out: <p>Observe…</p> +lite_mode_out: Observe… +--- +name: dimension sign +desc: The letter 'x' becomes a dimension sign when used between digits. +in: "Observe: 2x3." +out: "<p>Observe: 2×3.</p>" +--- +name: dimension sign with space after +in: "The room is 2x3 inches big." +out: "<p>The room is 2×3 inches big.</p>" +--- +name: dimension sign with spaces +in: "Observe: 2 x 4." +out: "<p>Observe: 2 × 4.</p>" +--- +name: dimension signs chained +in: "Observe: 2x3x4." +out: "<p>Observe: 2×3×4.</p>" +lite_mode_out: "Observe: 2×3×4." +--- +name: dimension signs with double primes +in: 'My mouse: 2.5" x 4".' +out: '<p>My mouse: 2.5″ × 4″.</p>' +--- +name: dimension signs with single primes +in: "My office: 5' x 4.5'." +out: "<p>My office: 5′ × 4.5′.</p>" +--- +name: trademark and copyright +desc: Conversion of trademark and copyright symbols. +in: one(TM), two(R), three(C). +out: <p>one™, two®, three©.</p> +lite_mode_out: one™, two®, three©. +--- +name: headers +desc: To make an entire paragraph into a Header, place “h<em>n</em>.” at its beginning, where <em>n</em> is a number from 1-6. +in: h3. Header 3 +out: <h3>Header 3</h3> +--- +name: blockquote +desc: To make an entire paragraph into a block quotation, place “bq.” before it. +in: |- + Any old text + + bq. A block quotation. + + Any old text +out: |- + <p>Any old text</p> + <blockquote> + <p>A block quotation.</p> + </blockquote> + <p>Any old text</p> +--- +name: em +desc: Emphasis to text is added by surrounding a phrase with underscores. In HTML, this often appears as <em>italics</em>. +in: I _believe_ every word. +out: <p>I <em>believe</em> every word.</p> +lite_mode_out: "I <em>believe</em> every word." +--- +name: strong +desc: Strength can be give to text by surrounding with asterisks. In HTML, this strength appears as <strong>bold</strong>. +in: And then? She *fell*! +out: <p>And then? She <strong>fell</strong>!</p> +lite_mode_out: "And then? She <strong>fell</strong>!" +--- +name: force bold italics +desc: Both italics and bold can be forced by doubling the underscores or asterisks. +in: |- + I __know__. + I **really** __know__. +out: |- + <p>I <i>know</i>.<br /> + I <b>really</b> <i>know</i>.</p> +--- +name: citation +desc: Use double question marks to indicate <em>citation</em>. The title of a book, for instance. +in: ??Cat's Cradle?? by Vonnegut +out: <p><cite>Cat’s Cradle</cite> by Vonnegut</p> +--- +name: code phrases +desc: Code phrases can be surrounded by at-symbols. +in: Convert with @r.to_html@ +out: <p>Convert with <code>r.to_html</code></p> +lite_mode_out: Convert with <code>r.to_html</code> +--- +name: code phrases not created with multiple email addresses +in: Please email why@domain.com or jason@domain.com. +out: <p>Please email why@domain.com or jason@domain.com.</p> +--- +name: del +desc: To indicate a passage which has been deleted, surround the passage with hypens. +in: I'm -sure- not sure. +out: <p>I’m <del>sure</del> not sure.</p> +--- +name: ins +desc: Pluses around a passage indicate its insertion. +in: You are a +pleasant+ child. +out: <p>You are a <ins>pleasant</ins> child.</p> +--- +name: superscript +desc: To superscript a phrase, surround with carets. +in: a ^2^ + b ^2^ = c ^2^ +out: <p>a <sup>2</sup> + b <sup>2</sup> = c <sup>2</sup></p> +--- +name: subscript +desc: To subscript, surround with tildes. +in: log ~2~ x +out: <p>log <sub>2</sub> x</p> +--- +name: span +desc: Lastly, if you find yourself needing to customize the style of a passage, use percent symbols to translate the passage as an HTML span. +in: I'm %unaware% of most soft drinks. +out: <p>I’m <span>unaware</span> of most soft drinks.</p> +--- +name: style span +desc: This way, you can apply style settings, as described in the next section to arbitrary phrases. +in: |- + I'm %{color:red}unaware% + of most soft drinks. +out: |- + <p>I’m <span style="color:red;">unaware</span><br /> + of most soft drinks.</p> +lite_mode_out: |- + I’m <span style="color:red;">unaware</span><br /> + of most soft drinks. +--- +name: css class +desc: A block can be tagged with a CSS class by circling the class in parentheses and placing it just before the period which marks the block. +in: p(example1). An example +out: <p class="example1">An example</p> +--- +name: css style +desc: Style settings can be provided directly by surrounding them in curly braces. +in: p{color:blue;margin:30px}. Spacey blue +out: <p style="color:blue;margin:30px;">Spacey blue</p> +--- +name: align justified +desc: Text inside blocks can be aligned in four basic ways. +in: p<>. justified +out: <p style="text-align:justify;">justified</p> +--- +name: indentation +desc: Indentation can also be specified by provide a single left paren for every 1em to the left. A single right paren for every 1em to the right. +in: p))). right ident 3em +out: <p style="padding-right:3em;">right ident 3em</p> +--- +name: indentation and alignment +desc: Identation may be coupled with alignment. +in: h2()>. Bingo. +out: <h2 style="padding-left:1em;padding-right:1em;text-align:right;" class="first">Bingo.</h2> +--- +name: numbered list +desc: To make a numbered list, place each item in its own paragraph, preceded by ”#”. +in: |- + # A first item + # A second item + # A third +out: |- + <ol> + <li>A first item</li> + <li>A second item</li> + <li>A third</li> + </ol> +--- +name: nested numbered lists +desc: These lists may be nested by increasing the number of pound symbols preceding child entries. +in: |- + # Fuel could be: + ## Coal + ## Gasoline + ## Electricity + # Humans need only: + ## Water + ## Protein +out: |- + <ol> + <li>Fuel could be: + <ol> + <li>Coal</li> + <li>Gasoline</li> + <li>Electricity</li> + </ol></li> + <li>Humans need only: + <ol> + <li>Water</li> + <li>Protein</li> + </ol></li> + </ol> +--- +name: bulleted list +desc: Bulleted lists use an asterisk in place of the pound. +in: |- + * A first item + * A second item + * A third +out: |- + <ul> + <li>A first item</li> + <li>A second item</li> + <li>A third</li> + </ul> +--- +name: nested bulleted lists +desc: These lists may be nested in like manner. +in: |- + * Fuel could be: + ** Coal + ** Gasoline + ** Electricity + * Humans need only: + ** Water + ** Protein +out: |- + <ul> + <li>Fuel could be: + <ul> + <li>Coal</li> + <li>Gasoline</li> + <li>Electricity</li> + </ul></li> + <li>Humans need only: + <ul> + <li>Water</li> + <li>Protein</li> + </ul></li> + </ul> +--- +name: links +desc: Basic links are comprised of a phrase which is linked to a <acronym title="Universal Resource Locator">URL</acronym>. Place the descriptive phrase in quotation marks. Follow it immediately by a colon and the URL. +in: I searched [Google -> http://google.com]. +out: <p>I searched <a href="http://google.com">Google</a>.</p> +lite_mode_out: I searched <a href="http://google.com">Google</a>. +--- +name: image +desc: You can embed an image in your Textile document by surrounding its URL with exclamation marks. +in: "!http://hobix.com/sample.jpg!" +out: <p><img src="http://hobix.com/sample.jpg" alt="" /></p> +lite_mode_out: <img src="http://hobix.com/sample.jpg" alt="" /> +--- +name: image title +desc: A title for the image can also be provided in parens, just before the closing exclamation. +in: "!openwindow1.gif(Bunny.)!" +out: <p><img src="openwindow1.gif" title="Bunny." alt="Bunny." /></p> +--- +name: image links +desc: Links can be attached to images with a colon. +in: "!openwindow1.gif!:http://hobix.com/" +out: <p><a href="http://hobix.com/"><img src="openwindow1.gif" alt="" /></a></p> +--- +name: image alignments +desc: Alignments can be applied as well to images. +in: |- + !>obake.gif! + + And others sat all round the small + machine and paid it to sing to them. +out: |- + <p style="float:right;" class="right"><img src="obake.gif" alt="" /></p> + <p>And others sat all round the small<br /> + machine and paid it to sing to them.</p> +--- +name: acronym definitions +desc: Definitions for acronyms can be provided by following an acronym with its definition in parens. +in: We use CSS(Cascading Style Sheets). +out: <p>We use <acronym title="Cascading Style Sheets"><span class="caps">CSS</span></acronym>.</p> +lite_mode_out: We use <acronym title="Cascading Style Sheets"><span class="caps">CSS</span></acronym>. +no_span_caps_out: <p>We use <acronym title="Cascading Style Sheets">CSS</acronym>.</p> +--- +name: extended block followed by pre block +in: |- + div.. Just a test. + + Second div. + + pre. A pre block ends it. +out: |- + <div>Just a test.</div> + <div>Second div.</div> + <pre>A pre block ends it.</pre> +--- +name: extended block followed by blockquote +in: |- + div.. Just a test. + + Second div. + + bq. A blockquote ends it. +out: |- + <div>Just a test.</div> + <div>Second div.</div> + <blockquote> + <p>A blockquote ends it.</p> + </blockquote> +--- +name: extended block followed by block code +in: |- + div.. Just a test. + + Second div. + + bc. A blockcode ends it. +out: |- + <div>Just a test.</div> + <div>Second div.</div> + <pre><code>A blockcode ends it.</code></pre> +--- +name: extended block followed by notextile block +in: |- + div.. Just a test. + + Second div. + + notextile. A notextile block ends it. +out: |- + <div>Just a test.</div> + <div>Second div.</div> + A notextile block ends it. +valid_out: false +--- +name: simple parentheses +in: |- + before (in parens) after +out: |- + <p>before (in parens) after</p> +--- +name: parentheses in underscores +in: |- + before _(in parens)_ after +out: |- + <p>before <em>(in parens)</em> after</p> +--- +name: parentheses in asterisks +in: |- + before *(in parens)* after +out: |- + <p>before <strong>(in parens)</strong> after</p> +--- +name: parentheses in underscores in quotes +in: |- + "before _(in parens)_ after" +out: |- + <p>“before <em>(in parens)</em> after”</p> +--- +name: underscores in parentheses +in: |- + one _two three_ (four _five six_) seven +out: |- + <p>one <em>two three</em> (four <em>five six</em>) seven</p> +--- +name: underscores in parentheses in quotes +in: |- + "one _two three_ (four _five six_) seven" +out: |- + <p>“one <em>two three</em> (four <em>five six</em>) seven”</p> +--- +name: underscores in parentheses 2 +in: |- + one (two _three four_) five +out: |- + <p>one (two <em>three four</em>) five</p> +--- +name: underscores in parentheses in quotes 2 +in: |- + "one (two _three four_) five" +out: |- + <p>“one (two <em>three four</em>) five”</p> + + +# ids are disabled in greencloth +#--- +#name: css id +#desc: An element ID can be given by prefixing the ID with a pound symbol and using it in place of the class. +#in: p(#big-red). Red here +#out: <p id="big-red">Red here</p> +#--- +#name: class and id combined +#desc: Class and ID can be combined by placing the class first. +#in: p(example1#big-red2). Red here +#out: <p class="example1" id="big-red2">Red here</p> + diff --git a/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/code.yml b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/code.yml new file mode 100644 index 0000000000000000000000000000000000000000..60c935e313352379d47117578b262718b2e2f518 --- /dev/null +++ b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/code.yml @@ -0,0 +1,173 @@ +in: do you like my @function@? +out: <p>do you like my <code>function</code>?</p> +--- +in: do you like my <code>function</code>? +out: <p>do you like my <code>function</code>?</p> +--- +in: 'This is an empty dictionary: @{}@' +out: '<p>This is an empty dictionary: <code>{}</code></p>' +--- +in: 'You can force [@code blocks@] like so.' +out: '<p>You can force <code>code blocks</code> like so.</p>' +# this markup is not allowed in RedCloth, so we don't allow it either: +#--- +# +#in: what about <pre>__inline__</pre> this? +#out: <p>what about <pre>__inline__</pre> this?</p> +--- +in: |- + <pre> + _a_ < _b_ + </pre> +out: |- + <pre>_a_ < _b_ + </pre> +--- +in: |- + <code> + _a_ < _b_ + </code> +out: |- + <pre><code>_a_ < _b_ + </code></pre> + +# greencloth doesn't support manual <pre><code> +#--- +#in: |- +# <pre><code> +# [a] < [b] +# </code></pre> +#out: |- +# <pre><code> +# [a] < [b] +# </code></pre> +--- +in: |- + * @foo@ + * @bar@ + * and @x@ is also. +out: |- + <ul> + <li><code>foo</code></li> + <li><code>bar</code></li> + <li>and <code>x</code> is also.</li> + </ul> + + +## +## special greencloth code block +## + +--- +in: |- + /-- + this is some really nice code + \-- +out: |- + <pre><code> this is some really nice code + </code></pre> +#--- +#in: |- +# codetitle. hello there +#out: |- +# <div class="codetitle">hello there</div> +#--- +#in: |- +# <code with a title> +# yippie +# </code> +#out: |- +# <div class="codetitle">with a title</div> +# <pre><code>yippie +# </code></pre> +#--- +#in: |- +# /-- a little note +# this is some really nice code +# and it continues +# \-- +#out: |- +# <div class="codetitle">a little note</div> +# <pre><code>this is some really nice code +# and it continues +# </code></pre> +#--- +#in: |- +# <code /etc/resolv.conf> +# nameserver 127.0.0.1 +# </code> +#out: |- +# <div class="codetitle">/etc/resolv.conf</div> +# <pre><code>nameserver 127.0.0.1 +# </code></pre> +--- +in: |- + <code>one fish</code> + + <code>two fish</code> + + <code>red fish</code> +out: |- + <pre><code>one fish</code></pre> + <pre><code>two fish</code></pre> + <pre><code>red fish</code></pre> +--- +in: |- + @@ a single line of code +out: |- + <pre><code>a single line of code</code></pre> +--- +in: |- + @@ a line of code with html <b>in it</b> +out: |- + <pre><code>a line of code with html <b>in it</b></code></pre> +--- +in: |- + /-- + a line of code with html <b>in it</b> + \-- +out: |- + <pre><code>a line of code with html <b>in it</b> + </code></pre> + + +## +## ensure custom greencloth filters don't apply to code blocks +## + +--- +in: |- + <code> + [aaa -> bbb] + </code> +out: |- + <pre><code>[aaa -> bbb] + </code></pre> +--- +in: "[@url in code http://riseup.net@]" +out: <p><code>url in code http://riseup.net</code></p> +--- +in: "@http://riseup.net@" +out: <p><code>http://riseup.net</code></p> +--- +in: inline <code>http://riseup.net</code> +out: <p>inline <code>http://riseup.net</code></p> + +## +## +## + +--- +in: |- + hi + <code> + wandering robot + </code> +out: |- + <p>hi<br /> + <pre><code>wandering robot + </code></pre></p> +--- +in: "<code>\r\ngrrrr. this makes me angry.\r\n</code>" +out: "<pre><code>grrrr. this makes me angry.\r\n</code></pre>" + diff --git a/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/code_redcloth.yml b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/code_redcloth.yml new file mode 100644 index 0000000000000000000000000000000000000000..a3db3176ebbb492c1d65f8da991afcf993b21a73 --- /dev/null +++ b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/code_redcloth.yml @@ -0,0 +1,218 @@ +--- +name: inline code +in: 'This is an empty dictionary: @{}@' +html: '<p>This is an empty dictionary: <code>{}</code></p>' +--- +name: inline code escapement +in: 'Please type @cat "file.txt" > otherfile.txt@ at the prompt.' +html: '<p>Please type <code>cat "file.txt" > otherfile.txt</code> at the prompt.</p>' +--- +name: inline code escapement with digits +in: |- + Regex-based string substitution with Ruby's gsub!: @"123<789".gsub!(/</, "") => "123789"@ +html: |- + <p>Regex-based string substitution with Ruby’s gsub!: <code>"123<789".gsub!(/</, "") => "123789"</code></p> +--- +name: inlne code escapement describing textile paragraph styling +in: 'This paragraph is aligned left but if you add this: @p>.@ to the beginning it will be aligned right.' +html: '<p>This paragraph is aligned left but if you add this: <code>p>.</code> to the beginning it will be aligned right.</p>' +--- +name: escapes code snippet containing html tag +in: 'At the top of each page, please put @<h2>Title</h2>@ in the HTML.' +html: '<p>At the top of each page, please put <code><h2>Title</h2></code> in the <span class="caps">HTML</span>.</p>' +--- +name: escaping in blockcode +in: 'bc. This is within a block of code, so < and > should be entities. You can talk about a <p class="foo"> tag if you wish and it will be properly escaped.' +html: |- + <pre><code>This is within a block of code, so < and > should be entities. You can talk about a <p class="foo"> tag if you wish and it will be properly escaped.</code></pre> +--- +name: escaping in normal text +in: |- + This is a regular paragraph. AT&T. £38 > $38. +html: |- + <p>This is a regular paragraph. AT&T. £38 > $38.</p> +latex: "This is a regular paragraph. AT\\&T. \\pounds{}38 \\textgreater{} \\$38.\n\n" +--- +name: preservation of existing entities +in: "Math fact: 3 < 5 & 5 > 3 but £6 > $6. Oh, and 2 ÷ 4 is ½." +html: "<p>Math fact: 3 < 5 & 5 > 3 but £6 > $6. Oh, and 2 ÷ 4 is ½.</p>" +latex: "Math fact: 3 \\textless{} 5 \\& 5 \\textgreater{} 3 but \\pounds{}6 \\textgreater{} \\$6. Oh, and 2 \\textdiv{} 4 is \\sfrac{1}{2}.\n\n" +--- +name: escaping of existing entities in blockcode +in: "bc. Math fact: 3 < 5 & 5 > 3 but £5 > $5." +html: "<pre><code>Math fact: 3 &lt; 5 &amp; 5 &gt; 3 but &pound;5 &#62; $5.</code></pre>" +latex: "\\begin{verbatim}\nMath fact: 3 < 5 & 5 > 3 but £5 > $5.\\end{verbatim}\n" +--- +name: no formatting within blockcode +in: |- + bc. __not italics__ +html: |- + <pre><code>__not italics__</code></pre> +--- +name: extended block code containing block start +in: |- + bc.. This is an extended bc. + + I saw a ship. It ate my elephant. +html: |- + <pre><code>This is an extended bc.</code> + + <code>I saw a ship. It ate my elephant.</code></pre> +--- +name: extended block code +in: |- + If you have a line or two of code or HTML to embed, use extended block code like so: + + bc.. ./foo.pl% + <p>foo outputs an HTML paragraph</p> + + <p>block of code keeps going until a different block signature is encountered</p> + + p. And then go back with a normal paragraph. +html: |- + <p>If you have a line or two of code or <span class="caps">HTML</span> to embed, use extended block code like so:</p> + <pre><code>./foo.pl% + <p>foo outputs an HTML paragraph</p></code> + + <code><p>block of code keeps going until a different block signature is encountered</p></code></pre> + <p>And then go back with a normal paragraph.</p> +--- +name: double-equals as inline notextile +in: |- + p. Regular paragraph + + ==Escaped portion -- will not be formatted by Textile at all== + + p. Back to normal. +html: |- + <p>Regular paragraph</p> + <p>Escaped portion -- will not be formatted by Textile at all</p> + <p>Back to normal.</p> +--- +name: notextile tags +in: |- + <notextile> + # *test* + </notextile> +html: |- + # *test* +valid_html: false +--- +name: unfinished notextile tag +in: |- + <notextile> + # *test* +html: |- + <p><notextile></p> + <ol> + <li><strong>test</strong></li> + </ol> +--- +name: inline notextile tags +in: 'This is how you make a link: <notextile>"link":http://www.redcloth.org</notextile>' +html: '<p>This is how you make a link: "link":http://www.redcloth.org</p>' +--- +name: code in list items +in: |- + * @foo@ + * @bar@ + * and @x@ is also. + +html: |- + <ul> + <li><code>foo</code></li> + <li><code>bar</code></li> + <li>and <code>x</code> is also.</li> + </ul> +--- +name: block code containing code avoids nesting code tags +in: |- + bc. A one-liner: @ruby -ne '($h||={}).fetch($_){puts $h[$_]=$_}'@ +html: |- + <pre><code>A one-liner: @ruby -ne '($h||={}).fetch($_){puts $h[$_]=$_}'@</code></pre> +--- +name: block code containing block start +in: |- + bc. I saw a ship. It ate my elephant. +html: |- + <pre><code>I saw a ship. It ate my elephant.</code></pre> +--- +name: block containing html tags +in: bc. Can I talk about <h2>Headings</h2> here? +html: |- + <pre><code>Can I talk about <h2>Headings</h2> here?</code></pre> +--- +name: escape latex standard symbols +in: "standard symbols # $ % & _ { }" +latex: "standard symbols \\# \\$ \\% \\& \\_ \\{ \\}\n\n" +--- +name: escape latex text symbols +in: "text symbols \\ ~ ^" +latex: "text symbols \\textbackslash{} \\~{} \\^{}\n\n" +--- +name: named html entities to latex +in: "… ½" +latex: \ldots{} \sfrac{1}{2}\n\n +--- +name: numeric html entities to latex +in: "… ½" +latex: \ldots{} \sfrac{1}{2}\n\n +--- +name: unclosed code tag +in: 'This is a some <code>code that will go unfinished' +html: '<p>This is a some <code>code that will go unfinished</code></p>' +valid_html: false +--- +name: code containing parentheses +in: 'p. @some_method(some_params, some => test);@ Oh dear this fails' +html: '<p><code>some_method(some_params, some => test);</code> Oh dear this fails</p>' + + +## +## greencloth doesn't support <pre><code> +## + +#--- +#name: unclosed pre tag +#in: '<pre><code>This is a pre that will go unfinished' +#html: '<pre><code>This is a pre that will go unfinished' +#valid_html: false +#--- +#name: no formatting within pre +#in: |- +# <pre> +# <code> +# # *test* +# __not italics__ +# no hard breaks +# </code> +# </pre> +#html: |- +# <pre> +# <code> +# # *test* +# __not italics__ +# no hard breaks +# </code> +# </pre> +#--- +#name: escaping in pre +#in: '<pre><code>This is within a block of code, so < and > should be entities. You can talk about a <p class="foo"> tag in #pre tags too.</code></pre>' +#html: '<pre><code>This is within a block of code, so < and > should be entities. You can talk about a <p #class="foo"> tag in pre tags too.</code></pre>' + +## +## greencloth doesn't allow html +## + +# changed because of filter_html +#--- +#name: unfinished script tag +#in: |- +# <script> +# function main(){} +#html: |- +# <script><br /> +# function main(){} +#valid_html: false + + diff --git a/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/definitions.yml b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/definitions.yml new file mode 100644 index 0000000000000000000000000000000000000000..95ea119bf3fc93cee0e10b6444e360b9a3578a04 --- /dev/null +++ b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/definitions.yml @@ -0,0 +1,82 @@ +name: redcloth definition list +in: |- + here is a RedCloth definition list: + + - yes := no + - no:=no + - maybe:= yes +out: |- + <p>here is a RedCloth definition list:</p> + <dl> + <dt>yes</dt> + <dd>no</dd> + <dt>no</dt> + <dd>no</dd> + <dt>maybe</dt> + <dd>yes</dd> + </dl> +--- +name: with line breaks +in: |- + - term := you can have line breaks + just like other lists + - line-spanning + term := hey, slick! +out: |- + <dl> + <dt>term</dt> + <dd>you can have line breaks<br /> + just like other lists</dd> + <dt>line-spanning<br /> + term</dt> + <dd>hey, slick!</dd> + </dl> +--- +name: double terms +in: |- + You can have multiple terms before a definition: + + - textile + - fabric + - cloth := woven threads +out: |- + <p>You can have multiple terms before a definition:</p> + <dl> + <dt>textile</dt> + <dt>fabric</dt> + <dt>cloth</dt> + <dd>woven threads</dd> + </dl> +--- +name: not a definition list +desc: a definition list with no definitions is not a definition list +in: |- + - textile + - fabric + - cloth +out: |- + <p>- textile<br /> + - fabric<br /> + - cloth</p> +--- +name: long definition list +in: |- + here is a long definition + + - some term := + *sweet* + + yes + + ok =: + - regular term := no +out: |- + <p>here is a long definition</p> + <dl> + <dt>some term</dt> + <dd><p><strong>sweet</strong></p> + <p>yes</p> + <p>ok</p></dd> + <dt>regular term</dt> + <dd>no</dd> + </dl> diff --git a/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/embed.yml b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/embed.yml new file mode 100644 index 0000000000000000000000000000000000000000..0974633fc3a3a1abded58c646773f5758cb57114 --- /dev/null +++ b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/embed.yml @@ -0,0 +1,7 @@ +--- +in: do you like my embedded blip.tv <embed src="http://blip.tv/play/Ac3GfI+2HA" type="application/x-shockwave-flash" width="720" height="510" allowscriptaccess="always" allowfullscreen="true"></embed>? +out: <p>do you like my embedded blip.tv <embed src="http://blip.tv/play/Ac3GfI+2HA" type="application/x-shockwave-flash" width="720" height="510" allowscriptaccess="always" allowfullscreen="true"></embed>?</p> +--- +in: do you like my embedded youtube <object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/suvDQoXA-TA&hl=en&fs=1"></param><param name="allowFullScreen" value="true"></param><embed src="http://www.youtube.com/v/suvDQoXA-TA&hl=en&fs=1" type="application/x-shockwave-flash" allowfullscreen="true" width="425" height="344"></embed></object>? +out: <p>do you like my embedded youtube <object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/suvDQoXA-TA&hl=en&fs=1"></param><param name="allowFullScreen" value="true"></param><embed src="http://www.youtube.com/v/suvDQoXA-TA&hl=en&fs=1" type="application/x-shockwave-flash" width="425" height="344" allowfullscreen="true"></embed></object>?</p> + diff --git a/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/extra_whitespace.yml b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/extra_whitespace.yml new file mode 100644 index 0000000000000000000000000000000000000000..ca3638d1ac5e75b405e438a993cab9a83db9b583 --- /dev/null +++ b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/extra_whitespace.yml @@ -0,0 +1,64 @@ +--- +name: header with 1 blank line below +in: |- + h3. Header + + text +out: |- + <h3>Header</h3> + <p>text</p> +--- +name: header with 2 blank lines below +in: |- + h3. Header + + + text +out: |- + <h3>Header</h3> + <p>text</p> +--- +name: header with 1 blank line above +in: |- + text + + h3. Header +out: |- + <p>text</p> + <h3>Header</h3> +--- +name: header with 2 blank lines above +in: |- + text + + + h3. Header +out: |- + <p>text</p> + <h3>Header</h3> +--- +name: header with 1 blank line above and with no text +in: |- + + h3. Header +out: <h3>Header</h3> +--- +name: header with 2 blank lines above and with no text +in: |- + + + h3. Header +out: <h3>Header</h3> +--- +name: header with 1 blank line below and with no text +in: |+ + h3. Header + +out: <h3>Header</h3> +--- +name: header with 2 blank lines below and with no text +in: |+ + h3. Header + + +out: <h3>Header</h3> diff --git a/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/html.yml b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/html.yml new file mode 100644 index 0000000000000000000000000000000000000000..6bd927e34693a9ac9642f282a1dc4deb1ff61270 --- /dev/null +++ b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/html.yml @@ -0,0 +1,35 @@ +--- +in: |- + this line <b>has</b> a lot of safe <a>html</a> in it, that is <em>allowed</em> +out: |- + <p>this line <b>has</b> a lot of safe <a>html</a> in it, that is <em>allowed</em></p> +--- +in: |- + but we do not allow <b id='5'>some</b> dangerous <span onmouseover='javascript:alert(1)'>attributes</span> +out: |- + <p>but we do not allow <b>some</b> dangerous <span>attributes</span></p> +--- +in: |- + this line ==<b>has</b> a lot of <a>html</a> in it==. +out: |- + <p>this line <b>has</b> a lot of <a>html</a> in it.</p> +--- +in: |- + we do not allow dangerous </div></textarea>html +out: |- + <p>we do not allow dangerous html</p> +--- +in: |- + <notextile>the notextile _tag_ turns off *textile*</notextile> +out: |- + the notextile _tag_ turns off *textile* +--- +in: |- + <!-- comments are ok --> +out: |- + <p><!-- comments are ok --></p> +--- +in: |- + <!-- unterminated comments are not ok +out: |- + <p><!— unterminated comments are not ok</p> diff --git a/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/images.yml b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/images.yml new file mode 100644 index 0000000000000000000000000000000000000000..85373db2d372c9e482488fb27e6aec5541160dc6 --- /dev/null +++ b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/images.yml @@ -0,0 +1,214 @@ +--- +in: This is an !image.jpg! +out: <p>This is an <img src="image.jpg" alt="" /></p> +--- +in: This is an !image.jpg(with alt text)! +out: <p>This is an <img src="image.jpg" title="with alt text" alt="with alt text" /></p> +--- +in: This is an !http://example.com/i/image.jpg! +out: <p>This is an <img src="http://example.com/i/image.jpg" alt="" /></p> +--- +in: This is an !http://example.com/i/image.jpg#a1! +out: <p>This is an <img src="http://example.com/i/image.jpg#a1" alt="" /></p> +--- +in: This is an !image.jpg!. +out: <p>This is an <img src="image.jpg" alt="" />.</p> +--- +in: This is an !image.jpg(with alt text)!. +out: <p>This is an <img src="image.jpg" title="with alt text" alt="with alt text" />.</p> +--- +in: This is an !http://example.com/i/image.jpg!. +out: <p>This is an <img src="http://example.com/i/image.jpg" alt="" />.</p> +--- +in: This is an !http://example.com/i/image.jpg#a1!. +out: <p>This is an <img src="http://example.com/i/image.jpg#a1" alt="" />.</p> +--- +in: This is not an image!!! +out: <p>This is not an image!!!</p> +--- +in: This is not an! image! +out: <p>This is not an! image!</p> +--- +in: This is an !http://example.com/i/image.jpg!:#1 +out: <p>This is an <a href="#1"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:#a +out: <p>This is an <a href="#a"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:#a1 +out: <p>This is an <a href="#a1"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:#a10 +out: <p>This is an <a href="#a10"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:index.html +out: <p>This is an <a href="index.html"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:index.html#1 +out: <p>This is an <a href="index.html#1"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:index.html#a1 +out: <p>This is an <a href="index.html#a1"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:index.html#a10 +out: <p>This is an <a href="index.html#a10"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:index.html?foo=bar +out: <p>This is an <a href="index.html?foo=bar"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:index.html?foo=bar#1 +out: <p>This is an <a href="index.html?foo=bar#1"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:index.html?foo=bar#a +out: <p>This is an <a href="index.html?foo=bar#a"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:index.html?foo=bar#a1 +out: <p>This is an <a href="index.html?foo=bar#a1"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:index.html?foo=bar#a10 +out: <p>This is an <a href="index.html?foo=bar#a10"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:http://example.com/ +out: <p>This is an <a href="http://example.com/"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:http://example.com/#1 +out: <p>This is an <a href="http://example.com/#1"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:http://example.com/#a +out: <p>This is an <a href="http://example.com/#a"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:http://example.com/#a1 +out: <p>This is an <a href="http://example.com/#a1"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:http://example.com/#a10 +out: <p>This is an <a href="http://example.com/#a10"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html +out: <p>This is an <a href="http://example.com/index.html"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html#1 +out: <p>This is an <a href="http://example.com/index.html#1"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html#a +out: <p>This is an <a href="http://example.com/index.html#a"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html#a1 +out: <p>This is an <a href="http://example.com/index.html#a1"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html#a10 +out: <p>This is an <a href="http://example.com/index.html#a10"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar +out: <p>This is an <a href="http://example.com/index.html?foo=bar"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar#1 +out: <p>This is an <a href="http://example.com/index.html?foo=bar#1"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar#a +out: <p>This is an <a href="http://example.com/index.html?foo=bar#a"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar#a1 +out: <p>This is an <a href="http://example.com/index.html?foo=bar#a1"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar#a10 +out: <p>This is an <a href="http://example.com/index.html?foo=bar#a10"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b +out: <p>This is an <a href="http://example.com/index.html?foo=bar&a=b"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#1 +out: <p>This is an <a href="http://example.com/index.html?foo=bar&a=b#1"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a +out: <p>This is an <a href="http://example.com/index.html?foo=bar&a=b#a"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a1 +out: <p>This is an <a href="http://example.com/index.html?foo=bar&a=b#a1"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a10 +out: <p>This is an <a href="http://example.com/index.html?foo=bar&a=b#a10"><img src="http://example.com/i/image.jpg" alt="" /></a></p> +--- +in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b. +out: <p>This is an <a href="http://example.com/index.html?foo=bar&a=b"><img src="http://example.com/i/image.jpg" alt="" /></a>.</p> +--- +in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#1. +out: <p>This is an <a href="http://example.com/index.html?foo=bar&a=b#1"><img src="http://example.com/i/image.jpg" alt="" /></a>.</p> +--- +in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a. +out: <p>This is an <a href="http://example.com/index.html?foo=bar&a=b#a"><img src="http://example.com/i/image.jpg" alt="" /></a>.</p> +--- +in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a1. +out: <p>This is an <a href="http://example.com/index.html?foo=bar&a=b#a1"><img src="http://example.com/i/image.jpg" alt="" /></a>.</p> +--- +in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a10. +out: <p>This is an <a href="http://example.com/index.html?foo=bar&a=b#a10"><img src="http://example.com/i/image.jpg" alt="" /></a>.</p> +--- +in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b, but this is not. +out: <p>This is an <a href="http://example.com/index.html?foo=bar&a=b"><img src="http://example.com/i/image.jpg" alt="" /></a>, but this is not.</p> +--- +in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#1, but this is not. +out: <p>This is an <a href="http://example.com/index.html?foo=bar&a=b#1"><img src="http://example.com/i/image.jpg" alt="" /></a>, but this is not.</p> +--- +in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a, but this is not. +out: <p>This is an <a href="http://example.com/index.html?foo=bar&a=b#a"><img src="http://example.com/i/image.jpg" alt="" /></a>, but this is not.</p> +--- +in: This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a1, but this is not. +out: <p>This is an <a href="http://example.com/index.html?foo=bar&a=b#a1"><img src="http://example.com/i/image.jpg" alt="" /></a>, but this is not.</p> +--- +in: (This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a10) This is not. +out: <p>(This is an <a href="http://example.com/index.html?foo=bar&a=b#a10"><img src="http://example.com/i/image.jpg" alt="" /></a>) This is not.</p> +--- +in: (This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b) This is not. +out: <p>(This is an <a href="http://example.com/index.html?foo=bar&a=b"><img src="http://example.com/i/image.jpg" alt="" /></a>) This is not.</p> +--- +in: (This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#1) This is not. +out: <p>(This is an <a href="http://example.com/index.html?foo=bar&a=b#1"><img src="http://example.com/i/image.jpg" alt="" /></a>) This is not.</p> +--- +in: (This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a) This is not. +out: <p>(This is an <a href="http://example.com/index.html?foo=bar&a=b#a"><img src="http://example.com/i/image.jpg" alt="" /></a>) This is not.</p> +--- +in: (This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a1) This is not. +out: <p>(This is an <a href="http://example.com/index.html?foo=bar&a=b#a1"><img src="http://example.com/i/image.jpg" alt="" /></a>) This is not.</p> +--- +in: (This is an !http://example.com/i/image.jpg!:http://example.com/index.html?foo=bar&a=b#a10) This is not. +out: <p>(This is an <a href="http://example.com/index.html?foo=bar&a=b#a10"><img src="http://example.com/i/image.jpg" alt="" /></a>) This is not.</p> +--- +name: image with relative src with dot +in: "!../../image.jpg!" +out: <p><img src="../../image.jpg" alt="" /></p> +--- +name: image with class +in: "!(myclass)image.jpg!" +out: <p><img src="image.jpg" class="myclass" alt="" /></p> +--- +name: image with class and dotspace +in: "!(myclass). image.jpg!" +out: <p><img src="image.jpg" class="myclass" alt="" /></p> +--- +name: image with class and relative src with dots +in: "!(myclass)../../image.jpg!" +out: <p><img src="../../image.jpg" class="myclass" alt="" /></p> +--- +name: image with class and dotspace and relative src with dots +in: "!(myclass). ../../image.jpg!" +out: <p><img src="../../image.jpg" class="myclass" alt="" /></p> +--- +name: image with style +in: "!{color:red}image.jpg!" +out: <p><img src="image.jpg" style="color:red;" alt="" /></p> +--- +name: image with style and dotspace +in: "!{color:red}. image.jpg!" +out: <p><img src="image.jpg" style="color:red;" alt="" /></p> +--- +name: image attributes has ampersand html entity in alt and title +in: "!/pictures/cat_and_fox.jpg(Trady Blix & The cartoon fox)!" +out: '<p><img src="/pictures/cat_and_fox.jpg" title="Trady Blix & The cartoon fox" alt="Trady Blix & The cartoon fox" /></p>' +--- +name: image attributes has double quote html entity in alt and title +in: '!/pictures/bacon.jpg(The fox said: "Have some chunky bacon")!' +out: '<p><img src="/pictures/bacon.jpg" title="The fox said: "Have some chunky bacon"" alt="The fox said: "Have some chunky bacon"" /></p>' +--- +name: image attributes has single quote html entity in alt and title +in: "!/pictures/bacon.jpg(The fox said: 'Have some chunky bacon')!" +out: '<p><img src="/pictures/bacon.jpg" title="The fox said: 'Have some chunky bacon'" alt="The fox said: 'Have some chunky bacon'" /></p>' diff --git a/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/indents.yml b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/indents.yml new file mode 100644 index 0000000000000000000000000000000000000000..a11c109d186da0d8434102b7b95281da2ef06705 --- /dev/null +++ b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/indents.yml @@ -0,0 +1,52 @@ +in: |- + > this is a quote + + this should not be in blockquote +out: |- + <blockquote>this is a quote</blockquote> + <p>this should not be in blockquote</p> +--- +in: |- + here is a regular paragraph + + > this one is a blockquote + > and lasts for two lines + + another regular paragraph +out: |- + <p>here is a regular paragraph</p> + <blockquote>this one is a blockquote<br /> + and lasts for two lines</blockquote> + <p>another regular paragraph</p> +#--- +#in: |- +# > here is a paragraph +# > +# >> with a nested paragraph +# >> within it. +# > +# > what do you think about that? +#out: .... +--- +in: |- + > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet, + > consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. + > Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. + > + > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse + > id sem consectetuer libero luctus adipiscing. +out: |- + <blockquote>This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet, + consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. + Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. + + Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse + id sem consectetuer libero luctus adipiscing.</blockquote> +in: |- + > This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus. + > + > Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse id sem consectetuer libero luctus adipiscing. +out: |- + <blockquote>This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus. Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.<br /> + <br /> + Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse id sem consectetuer libero luctus adipiscing.</blockquote> diff --git a/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/links.yml b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/links.yml new file mode 100644 index 0000000000000000000000000000000000000000..271a77714bc16ed8f24e59dfdb2b79fd1e8a1fa7 --- /dev/null +++ b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/links.yml @@ -0,0 +1,75 @@ +--- +in: this is a [plain link] in some text +out: <p>this is a <a href="/page/plain-link">plain link</a> in some text</p> +--- +in: this is a [namespaced / link] in some text +out: <p>this is a <a href="/namespaced/link">link</a> in some text</p> +--- +in: this is a [link to -> something else ] in some text +out: <p>this is a <a href="/page/something-else">link to</a> in some text</p> +--- +in: this is a [link to -> namespace / something else ] in some text +out: <p>this is a <a href="/namespace/something-else">link to</a> in some text</p> +--- +in: this is a [link to -> /an/absolute/path] in some text +out: <p>this is a <a href="/an/absolute/path">link to</a> in some text</p> +--- +in: this is a [link to -> https://riseup.net] a url +out: <p>this is a <a href="https://riseup.net">link to</a> a url</p> +--- +in: url in brackets [https://riseup.net/] +out: <p>url in brackets <a href="https://riseup.net/">riseup.net</a></p> +--- +in: a [name-link] in need of humanizing +out: <p>a <a href="/page/name-link">name link</a> in need of humanizing</p> +--- +in: link to a user [/blue] +out: <p>link to a user <a href="/blue">blue</a></p> +--- +in: "[link to -> /-dashes/in/the/link-]" +out: <p><a href="/-dashes/in/the/link-">link to</a></p> +--- +in: "links [with_underscores] should keep underscore" +out: <p>links <a href="/page/with_underscores">with_underscores</a> should keep underscore</p> +--- +in: |- + * [link to -> this] +out: |- + <ul> + <li><a href="/page/this">link to</a></li> + </ul> +--- +in: |- + * [https://riseup.net/] +out: |- + <ul> + <li><a href="https://riseup.net/">riseup.net</a></li> + </ul> +--- +in: "[bad ->-> link]" +out: <p><a href="#error">bad</a></p> +--- +in: "[bad link -> ]" +out: <p><a href="#error">bad link</a></p> +--- +in: "[ -> bad link]" +out: <p><a href="/page/bad-link"></a></p> +--- +in: "make anchors [#here#] or [# maybe here #] or [# over -> there #]" +out: "<p>make anchors <a name=\"here\">here</a> or <a name=\"maybe-here\">maybe here</a> or <a name=\"there\">over</a></p>" +--- +in: "link to [anchors # like so] or [ maybe -> like #so ] or [just -> #so] or [#so]" +out: "<p>link to <a href=\"/page/anchors#like-so\">anchors </a> or <a href=\"/page/like#so\"> maybe</a> or <a href=\"#so\">just</a> or <a href=\"#so\">so</a></p>" +--- +in: "[link -> #5] to a numeric anchor [# 5 #]" +out: "<p><a href=\"#5\">link</a> to a numeric anchor <a name=\"5\">5</a></p>" + +## +## failing tests +## + +#--- +#in: "[link to -> /+plus/in/the/link+]" +#out: <p><a href="/+plus/in/the/plus+">link to</a></p> + + diff --git a/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/lists.yml b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/lists.yml new file mode 100644 index 0000000000000000000000000000000000000000..d1c5fe5522c61531a34ae26c5928371d00828f60 --- /dev/null +++ b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/lists.yml @@ -0,0 +1,371 @@ +--- +name: hard break in list +in: |- + * first line + * second + line + * third line +out: |- + <ul> + <li>first line</li> + <li>second<br /> + line</li> + <li>third line</li> + </ul> +--- +name: mixed nesting +in: |- + * bullet + *# number + *# number + *#* bullet + *# number + *# number with + a break + * bullet + ** okay +out: |- + <ul> + <li>bullet + <ol> + <li>number</li> + <li>number + <ul> + <li>bullet</li> + </ul></li> + <li>number</li> + <li>number with<br /> + a break</li> + </ol></li> + <li>bullet + <ul> + <li>okay</li> + </ul></li> + </ul> +--- +name: list continuation +in: |- + # one + # two + # three + + # one + # two + # three + + #_ four + # five + # six +out: |- + <ol> + <li>one</li> + <li>two</li> + <li>three</li> + </ol> + <ol> + <li>one</li> + <li>two</li> + <li>three</li> + </ol> + <ol start="4"> + <li>four</li> + <li>five</li> + <li>six</li> + </ol> +valid_html: false +comment: there's not a good, valid alternative to the start attribute +--- +name: continue after break +in: |- + # one + # two + # three + + test + + #_ four + # five + # six + + test + + #_ seven + # eight + # nine +out: |- + <ol> + <li>one</li> + <li>two</li> + <li>three</li> + </ol> + <p>test</p> + <ol start="4"> + <li>four</li> + <li>five</li> + <li>six</li> + </ol> + <p>test</p> + <ol start="7"> + <li>seven</li> + <li>eight</li> + <li>nine</li> + </ol> +valid_html: false +comment: there's not a good, valid alternative to the start attribute +--- +name: continue list when prior list contained nested list +in: |- + # one + # two + # three + + #_ four + # five + ## sub-note + ## another sub-note + # six + + #_ seven + # eight + # nine +out: |- + <ol> + <li>one</li> + <li>two</li> + <li>three</li> + </ol> + <ol start="4"> + <li>four</li> + <li>five + <ol> + <li>sub-note</li> + <li>another sub-note</li> + </ol></li> + <li>six</li> + </ol> + <ol start="7"> + <li>seven</li> + <li>eight</li> + <li>nine</li> + </ol> +valid_html: false +comment: there's not a good, valid alternative to the start attribute +--- +name: list start number +in: |- + #293 two ninety three + # two ninety four + # two ninety five + + #9 nine + # ten + # eleven +out: |- + <ol start="293"> + <li>two ninety three</li> + <li>two ninety four</li> + <li>two ninety five</li> + </ol> + <ol start="9"> + <li>nine</li> + <li>ten</li> + <li>eleven</li> + </ol> +valid_html: false +comment: there's not a good, valid alternative to the start attribute +--- +name: continue list after started list +in: |- + #9 nine + # ten + # eleven + + #_ twelve + # thirteen + # fourteen +out: |- + <ol start="9"> + <li>nine</li> + <li>ten</li> + <li>eleven</li> + </ol> + <ol start="12"> + <li>twelve</li> + <li>thirteen</li> + <li>fourteen</li> + </ol> +valid_html: false +comment: there's not a good, valid alternative to the start attribute +--- +name: end notes +in: |- + h2. End Notes + + # End Notes should be a numbered list + # Like this + # They must have anchors in the text + + h2. See Also + + * See Also notes should be bullets + * Like this + +out: |- + <h2 class="first">End Notes</h2> + <ol> + <li>End Notes should be a numbered list</li> + <li>Like this</li> + <li>They must have anchors in the text</li> + </ol> + <h2>See Also</h2> + <ul> + <li>See Also notes should be bullets</li> + <li>Like this</li> + </ul> +--- +name: ordered list immediately following paragraph +desc: Normally a paragraph and a list that follows it should be separated by two newlines. Textile-2.0.0 recognizes the list even when separated by only one newline, but creates invalid XHTML by placing the list inside the paragraph. RedCloth recognizes the pattern for backward compatibility, but creates valid XHTML. +in: |- + A simple example. + # One + # Two +out: |- + <p>A simple example.</p> + <ol> + <li>One</li> + <li>Two</li> + </ol> +--- +name: unordered list immediately following paragraph +in: |- + A simple example. + * One + * Two +out: |- + <p>A simple example.</p> + <ul> + <li>One</li> + <li>Two</li> + </ul> +--- +name: ordered list immediately following extended block +in: |- + div.. Here it comes. + + A simple example. + # One + # Two +out: |- + <div>Here it comes.</div> + <div>A simple example.</div> + <ol> + <li>One</li> + <li>Two</li> + </ol> +--- +name: unordered list immediately following extended block +in: |- + div.. Here it comes. + + A simple example. + * One + * Two +out: |- + <div>Here it comes.</div> + <div>A simple example.</div> + <ul> + <li>One</li> + <li>Two</li> + </ul> +--- +name: list with double colons +in: |- + * one:: fish + * TWO:: fish + * three:: +out: |- + <ul> + <li><b>one:</b> fish</li> + <li><b><span class="caps">TWO</span>:</b> fish</li> + <li><b>three:</b> </li> + </ul> +--- +name: lists with links and linefeed +in: "* http://riseup.net\r\n* http://riseup.net" +out: |- + <ul> + <li><a href="http://riseup.net">riseup.net</a></li> + <li><a href="http://riseup.net">riseup.net</a></li> + </ul> +--- +name: list with too many headings +in: |- + h5. heading h5 + + h4. heading h4 + + h3. and heading h3 + + h2. en die + + h1. ook! + + + Moet je dat zien? + + + Kijk dan! + + + Er moet bullet points er zijn: + + + * een + * twee + * drie + * vier + * vijf + + + Er moet nummers erbij: + + + # een + # twee + # drie + # vier + # vijf + + + Ook belangrijk: + + + + *Niks werkt!* +out: |- + <h5>heading h5</h5> + <h4>heading h4</h4> + <h3>and heading h3</h3> + <h2 class="first">en die</h2> + <h1>ook!</h1> + <p>Moet je dat zien?</p> + <p>Kijk dan!</p> + <p>Er moet bullet points er zijn:</p> + <ul> + <li>een</li> + <li>twee</li> + <li>drie</li> + <li>vier</li> + <li>vijf</li> + </ul> + <p>Er moet nummers erbij:</p> + <ol> + <li>een</li> + <li>twee</li> + <li>drie</li> + <li>vier</li> + <li>vijf</li> + </ol> + <p>Ook belangrijk:</p> + <p><strong>Niks werkt!</strong></p> + diff --git a/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/macros.yml b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/macros.yml new file mode 100644 index 0000000000000000000000000000000000000000..555037972367b7c736993a6adc15fabdf465603b --- /dev/null +++ b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/macros.yml @@ -0,0 +1,23 @@ +--- +name: toc without [:outline] option should pass through. +in: |- + [[toc]] + + h1. hi +out: |- + <p>[[toc]]</p> + + <h1 class="first">hi</h1> + +#--- +#name: bad macro +#in: |- +# [[this_macro_does_not_exist]] +#out: |- +# <p>[[this_macro_does_not_exist]]</p> + + + + + + diff --git a/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/outline.yml b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/outline.yml new file mode 100644 index 0000000000000000000000000000000000000000..b47c9ad2027e17836abb23c500e389b0283ac572 --- /dev/null +++ b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/outline.yml @@ -0,0 +1,392 @@ +--- +name: empty outline +in: |- + [[toc]] +out: |- + <ul class="toc"> + </ul> +--- +name: fruity outline +in: |- + [[toc]] + + h1. Fruits + + h2. Tasty Apples + + h3. Green + + h3. Red + + h2. Pears + + h1. Vegetables + + h2. Turnips + + h2. Green Beans +out: |- + <ul class="toc"> + <li class="toc1"><a href="#fruits"><span>1</span> Fruits</a></li> + <ul> + <li class="toc2"><a href="#tasty-apples"><span>1.1</span> Tasty Apples</a></li> + <ul> + <li class="toc3"><a href="#green"><span>1.1.1</span> Green</a></li> + <li class="toc3"><a href="#red"><span>1.1.2</span> Red</a></li> + </ul> + <li class="toc2"><a href="#pears"><span>1.2</span> Pears</a></li> + </ul> + <li class="toc1"><a href="#vegetables"><span>2</span> Vegetables</a></li> + <ul> + <li class="toc2"><a href="#turnips"><span>2.1</span> Turnips</a></li> + <li class="toc2"><a href="#green-beans"><span>2.2</span> Green Beans</a></li> + </ul> + </ul> + <h1 class="first"><a name="fruits"></a>Fruits<a class="anchor" href="#fruits">¶</a></h1> + <h2><a name="tasty-apples"></a>Tasty Apples<a class="anchor" href="#tasty-apples">¶</a></h2> + <h3><a name="green"></a>Green<a class="anchor" href="#green">¶</a></h3> + <h3><a name="red"></a>Red<a class="anchor" href="#red">¶</a></h3> + <h2><a name="pears"></a>Pears<a class="anchor" href="#pears">¶</a></h2> + <h1><a name="vegetables"></a>Vegetables<a class="anchor" href="#vegetables">¶</a></h1> + <h2><a name="turnips"></a>Turnips<a class="anchor" href="#turnips">¶</a></h2> + <h2><a name="green-beans"></a>Green Beans<a class="anchor" href="#green-beans">¶</a></h2> +--- +name: test with \r\n +in: "[[toc]]\r\n\r\nh1. Bats\r\n\r\nh1. Squirrels\r\n" +out: |- + <ul class="toc"> + <li class="toc1"><a href="#bats"><span>1</span> Bats</a></li> + <li class="toc1"><a href="#squirrels"><span>2</span> Squirrels</a></li> + </ul> + <h1 class="first"><a name="bats"></a>Bats<a class="anchor" href="#bats">¶</a></h1> + <h1><a name="squirrels"></a>Squirrels<a class="anchor" href="#squirrels">¶</a></h1> +--- +name: test name collisions +in: |- + h1. Corvidae + + h2. Crow + + h2. Raven + + h2. Rook + + h1. Chess Pieces + + h2. Queen + + h2. Rook + + h1. Card Games + + h2. Hearts + + h2. Rook + +out: |- + <h1 class="first"><a name="corvidae"></a>Corvidae<a class="anchor" href="#corvidae">¶</a></h1> + <h2><a name="crow"></a>Crow<a class="anchor" href="#crow">¶</a></h2> + <h2><a name="raven"></a>Raven<a class="anchor" href="#raven">¶</a></h2> + <h2><a name="rook"></a>Rook<a class="anchor" href="#rook">¶</a></h2> + <h1><a name="chess-pieces"></a>Chess Pieces<a class="anchor" href="#chess-pieces">¶</a></h1> + <h2><a name="queen"></a>Queen<a class="anchor" href="#queen">¶</a></h2> + <h2><a name="rook_2"></a>Rook<a class="anchor" href="#rook_2">¶</a></h2> + <h1><a name="card-games"></a>Card Games<a class="anchor" href="#card-games">¶</a></h1> + <h2><a name="hearts"></a>Hearts<a class="anchor" href="#hearts">¶</a></h2> + <h2><a name="rook_3"></a>Rook<a class="anchor" href="#rook_3">¶</a></h2> +--- +name: test with links +in: |- + h1. Russian Anarchists + + h2. Michel [Bakunin -> http://en.wikipedia.org/wiki/Mikhail_Bakunin] + + h2. [Peter -> http://en.wikipedia.org/wiki/Peter_Kropotkin] Kropotkin + + h1. Russian-American Anarchists + + h2. [Emma Goldman -> http://en.wikipedia.org/wiki/Emma_Goldman] + + h2. Alexander [Berkman -> http://en.wikipedia.org/wiki/Alexander_Berkman] +out: |- + <h1 class="first"><a name="russian-anarchists"></a>Russian Anarchists<a class="anchor" href="#russian-anarchists">¶</a></h1> + <h2><a name="michel-bakunin"></a>Michel <a href="http://en.wikipedia.org/wiki/Mikhail_Bakunin">Bakunin</a><a class="anchor" href="#michel-bakunin">¶</a></h2> + <h2><a name="peter-kropotkin"></a><a href="http://en.wikipedia.org/wiki/Peter_Kropotkin">Peter</a> Kropotkin<a class="anchor" href="#peter-kropotkin">¶</a></h2> + <h1><a name="russian-american-anarchists"></a>Russian-American Anarchists<a class="anchor" href="#russian-american-anarchists">¶</a></h1> + <h2><a name="emma-goldman"></a><a href="http://en.wikipedia.org/wiki/Emma_Goldman">Emma Goldman</a><a class="anchor" href="#emma-goldman">¶</a></h2> + <h2><a name="alexander-berkman"></a>Alexander <a href="http://en.wikipedia.org/wiki/Alexander_Berkman">Berkman</a><a class="anchor" href="#alexander-berkman">¶</a></h2> +--- +name: double trouble +in: |- + h1. Title + + h3. Under first + + h1. Title + + h3. Under second +out: |- + <h1 class="first"><a name="title"></a>Title<a class="anchor" href="#title">¶</a></h1> + <h3><a name="under-first"></a>Under first<a class="anchor" href="#under-first">¶</a></h3> + <h1><a name="title_2"></a>Title<a class="anchor" href="#title_2">¶</a></h1> + <h3><a name="under-second"></a>Under second<a class="anchor" href="#under-second">¶</a></h3> +--- +name: setext trees +in: |- + Evergreens + ========== + + h3. Cedar + + h3. Redwood + + h3. Fir + + Deciduous + ========= + + h3. Maple + + Oaks + ---- + + h3. White Oak + + h3. Red Oak +out: |- + <h1 class="first"><a name="evergreens"></a>Evergreens<a class="anchor" href="#evergreens">¶</a></h1> + <h3><a name="cedar"></a>Cedar<a class="anchor" href="#cedar">¶</a></h3> + <h3><a name="redwood"></a>Redwood<a class="anchor" href="#redwood">¶</a></h3> + <h3><a name="fir"></a>Fir<a class="anchor" href="#fir">¶</a></h3> + <h1><a name="deciduous"></a>Deciduous<a class="anchor" href="#deciduous">¶</a></h1> + <h3><a name="maple"></a>Maple<a class="anchor" href="#maple">¶</a></h3> + <h2><a name="oaks"></a>Oaks<a class="anchor" href="#oaks">¶</a></h2> + <h3><a name="white-oak"></a>White Oak<a class="anchor" href="#white-oak">¶</a></h3> + <h3><a name="red-oak"></a>Red Oak<a class="anchor" href="#red-oak">¶</a></h3> +--- +name: multiline headings +in: |- + h1. section one line one + line two + + section one text + + h2. subsection + without content + + h1. section two line one + line two + + section two text +out: |- + <h1 class="first"><a name="section-one-line-one-line-two"></a>section one line one<br /> + line two<a class="anchor" href="#section-one-line-one-line-two">¶</a></h1> + <p>section one text</p> + <h2><a name="subsection-without-content"></a>subsection<br /> + without content<a class="anchor" href="#subsection-without-content">¶</a></h2> + <h1><a name="section-two-line-one-line-two"></a>section two line one<br /> + line two<a class="anchor" href="#section-two-line-one-line-two">¶</a></h1> + <p>section two text</p> +--- +name: weird chars +in: |- + h1. i eat 'food' + + h1. it is yŭmmy +out: |- + <h1 class="first"><a name="i-eat-food"></a>i eat ‘food’<a class="anchor" href="#i-eat-food">¶</a></h1> + <h1><a name="it-is-yŭmmy"></a>it is yŭmmy<a class="anchor" href="#it-is-yŭmmy">¶</a></h1> +--- +name: badly organized fruits +in: |- + h1. Fruits + + h3. Green Apples + + h2. Tasty Apples + + h2. Pears + + h1. Vegetables + + h2. Turnips + + h2. Green Beans +out: |- + <h1 class="first"><a name="fruits"></a>Fruits<a class="anchor" href="#fruits">¶</a></h1> + <h3><a name="green-apples"></a>Green Apples<a class="anchor" href="#green-apples">¶</a></h3> + <h2><a name="tasty-apples"></a>Tasty Apples<a class="anchor" href="#tasty-apples">¶</a></h2> + <h2><a name="pears"></a>Pears<a class="anchor" href="#pears">¶</a></h2> + <h1><a name="vegetables"></a>Vegetables<a class="anchor" href="#vegetables">¶</a></h1> + <h2><a name="turnips"></a>Turnips<a class="anchor" href="#turnips">¶</a></h2> + <h2><a name="green-beans"></a>Green Beans<a class="anchor" href="#green-beans">¶</a></h2> +--- +name: untitled leading section +in: |- + + welcome to our great list of fruits and vegetables + + h1. Fruits + + h2. Pears + + h1. Vegetables + + h2. Green Beans +out: |- + <p>welcome to our great list of fruits and vegetables</p> + <h1 class="first"><a name="fruits"></a>Fruits<a class="anchor" href="#fruits">¶</a></h1> + <h2><a name="pears"></a>Pears<a class="anchor" href="#pears">¶</a></h2> + <h1><a name="vegetables"></a>Vegetables<a class="anchor" href="#vegetables">¶</a></h1> + <h2><a name="green-beans"></a>Green Beans<a class="anchor" href="#green-beans">¶</a></h2> +--- +name: plain old text +in: |- + curiouser and curiouser + +out: |- + <p>curiouser and curiouser</p> + +--- +name: weird and nested +in: |- + loose stuff + + h1. Highest + + lower + ----------- + + lower text + + h2. even lower + + h3. lowest + + lowest text + + h3. lowest and blankest + + high as they get + ================= + + h2. underling + + underling text +out: |- + <p>loose stuff</p> + <h1 class="first"><a name="highest"></a>Highest<a class="anchor" href="#highest">¶</a></h1> + <h2><a name="lower"></a>lower<a class="anchor" href="#lower">¶</a></h2> + <p>lower text</p> + <h2><a name="even-lower"></a>even lower<a class="anchor" href="#even-lower">¶</a></h2> + <h3><a name="lowest"></a>lowest<a class="anchor" href="#lowest">¶</a></h3> + <p>lowest text</p> + <h3><a name="lowest-and-blankest"></a>lowest and blankest<a class="anchor" href="#lowest-and-blankest">¶</a></h3> + <h1><a name="high-as-they-get"></a>high as they get<a class="anchor" href="#high-as-they-get">¶</a></h1> + <h2><a name="underling"></a>underling<a class="anchor" href="#underling">¶</a></h2> + <p>underling text</p> +--- +name: overdecorated +in: |- + h2. _emphasis_ + + __italicized__ + -------------- + + h2. *strong* + + **bold** + -------- + + h2. ??citation?? + + -deleted text- + -------------- + + h2. +inserted text+ + + ^superscript^ + ------------- + + h2. ~subscript~ + + @code@ + ------ + + h2. [-table-] + + [# Heading anchor -> head_anchor #] + ----------------------------------- + + h2. Anchor _within_ [# heading -> head_anchor #] + + Dots ... + -------- + +out: |- + <h2 class="first"><a name="emphasis"></a><em>emphasis</em><a class="anchor" href="#emphasis">¶</a></h2> + <h2><a name="italicized"></a><i>italicized</i><a class="anchor" href="#italicized">¶</a></h2> + <h2><a name="strong"></a><strong>strong</strong><a class="anchor" href="#strong">¶</a></h2> + <h2><a name="bold"></a><b>bold</b><a class="anchor" href="#bold">¶</a></h2> + <h2><a name="citation"></a><cite>citation</cite><a class="anchor" href="#citation">¶</a></h2> + <h2><a name="deleted-text"></a><del>deleted text</del><a class="anchor" href="#deleted-text">¶</a></h2> + <h2><a name="inserted-text"></a><ins>inserted text</ins><a class="anchor" href="#inserted-text">¶</a></h2> + <h2><a name="superscript"></a><sup>superscript</sup><a class="anchor" href="#superscript">¶</a></h2> + <h2><a name="subscript"></a><sub>subscript</sub><a class="anchor" href="#subscript">¶</a></h2> + <h2><a name="code"></a><code>code</code><a class="anchor" href="#code">¶</a></h2> + <h2><a name="table"></a><del>table</del><a class="anchor" href="#table">¶</a></h2> + <h2><a name="heading-anchor"></a><a name="head_anchor">Heading anchor</a><a class="anchor" href="#heading-anchor">¶</a></h2> + <h2><a name="anchor-within-heading"></a>Anchor <em>within</em> <a name="head_anchor">heading</a><a class="anchor" href="#anchor-within-heading">¶</a></h2> + <h2><a name="dots"></a>Dots …<a class="anchor" href="#dots">¶</a></h2> + +--- +name: leading and trailing whitespace +in: |- + Clearly a Section + === + + still a section + + --- + more text + + <code> + coding + + not a section + + --- + more text here + </code> +out: |- + <h1 class="first"><a name="clearly-a-section"></a>Clearly a Section<a class="anchor" href="#clearly-a-section">¶</a></h1> + <h2><a name="still-a-section"></a>still a section<a class="anchor" href="#still-a-section">¶</a></h2> + <p>more text</p> + <pre><code> coding + not a section + --- + more text here + </code></pre> +--- +name: code block weirdness +in: |- + real stuff + ---- + + <code> + + a.. b + ----- + + aa... bb + ----- + + </code> +out: |- + <h2 class="first"><a name="real-stuff"></a>real stuff<a class="anchor" href="#real-stuff">¶</a></h2> + <pre><code> + a.. b + ----- + aa... bb + ----- + </code></pre> diff --git a/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/sections.yml b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/sections.yml new file mode 100644 index 0000000000000000000000000000000000000000..d90c98f61cc9768e73233ee58e9e12119a392045 --- /dev/null +++ b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/sections.yml @@ -0,0 +1,108 @@ +--- +name: one section no heading +in: |- + start unheaded section + + line line line +out: |- + <div class="wiki_section" id="wiki_section-0"> + <p>start unheaded section</p> + <p>line line line</p> + </div> +--- +name: one section with heading +in: |- + h2. are you ready?!!? + + here we go now! +out: |- + <div class="wiki_section" id="wiki_section-0"> + <h2 class="first">are you ready?!!?</h2> + <p>here we go now!</p> + </div> +--- +name: some mixed style sections +in: |- + + h2. first section + + some blahs + + second section + ============== + + more lalas +out: |- + <div class="wiki_section" id="wiki_section-0"> + <h2 class="first">first section</h2> + <p>some blahs</p> + </div> + <div class="wiki_section" id="wiki_section-1"> + <h1>second section</h1> + <p>more lalas</p> + </div> +--- +name: section without heading +in: |- + some text + one more line of text without a heading + + some blahs + + h1. first section heading here + + more lalas +out: |- + <div class="wiki_section" id="wiki_section-0"> + <p>some text<br /> + one more line of text without a heading</p> + <p>some blahs</p> + </div> + <div class="wiki_section" id="wiki_section-1"> + <h1 class="first">first section heading here</h1> + <p>more lalas</p> + </div> +--- +name: multiple sections with text +in: |- + Section One + ----------- + section one line one is here + section one line two is next + + Here is section one still + + Section Two + ========== + Section two first line + Section two another line + + + h2. Section 3 with h2 + + One more line for section 3 + + h3. final section 4 + + section 4 first non-blank line +out: |- + <div class="wiki_section" id="wiki_section-0"> + <h2 class="first">Section One</h2> + <p>section one line one is here<br /> + section one line two is next</p> + <p>Here is section one still</p> + </div> + <div class="wiki_section" id="wiki_section-1"> + <h1>Section Two</h1> + <p>Section two first line<br /> + Section two another line</p> + </div> + + <div class="wiki_section" id="wiki_section-2"> + <h2>Section 3 with h2</h2> + <p>One more line for section 3</p> + </div> + <div class="wiki_section" id="wiki_section-3"> + <h3>final section 4</h3> + <p>section 4 first non-blank line</p> + </div> diff --git a/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/security.yml b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/security.yml new file mode 100644 index 0000000000000000000000000000000000000000..02a40408bb379012e534982a405499cb8056f171 --- /dev/null +++ b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/security.yml @@ -0,0 +1,60 @@ +--- +in: |- + <!--[if gte IE 4]><SCRIPT>alert('XSS');</SCRIPT><![endif]--> +out: |- + <p><!--<a href="/page/if-gte-ie-4">if gte IE 4</a>>alert('XSS');<!<a href="/page/endif">endif</a>--></p> +--- +in: |- + <script>alert(1)</script> +out: |- + <p>alert(1)</p> +--- +in: |- + <a href='javascript:alert(1)'>hello</a> +out: |- + <p><a>hello</a></p> +--- +in: |- + [ hello -> javascript:alert(1) ] +out: |- + <p><a href="/page/javascript-alert-1"> hello</a></p> +--- +in: |- + <img src=javascript:alert('XSS')> +out: |- + <p><img></p> +--- +in: |- + !javascript:alert('XSS')! +out: |- + <p><img src="javascript:alert" title="'XSS'" alt="'XSS'" /></p> +--- +in: |- + <code onmouseover="javascript:alert(1)">blah</code> +out: |- + <pre><code>blah</code></pre> +--- +in: |- + xx <code onmouseover="javascript:alert(1)">blah</code> xx +out: |- + <p>xx <code>blah</code> xx</p> +--- +in: |- + [ nasty -> link </textarea> ] +out: |- + <p><a href="/link/textarea"> nasty</a></p> +--- +in: |- + [ <b>nasty</b> <script>alert(1)</script> -> link ] +out: |- + <p><a href="/page/link"> <b>nasty</b> <script>alert(1)</script></a></p> +--- +in: |- + [ nasty -> http://riseup.net/"> <script>alert(1)</script> ] +out: |- + <p><a href="http://riseup.net/"> <script>alert(1)</script> "> nasty</a></p> +--- +in: |- + <notextile><script>alert(6)</script></notextile> +out: |- + alert(6) diff --git a/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/table.yml b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/table.yml new file mode 100644 index 0000000000000000000000000000000000000000..88488ff52d70f2cef1c4198642ca054599955748 --- /dev/null +++ b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/table.yml @@ -0,0 +1,324 @@ +--- +in: | + |a|b|c| + |1|2|3| + + h3. A header after the table +out: |- + <table> + <tr class="odd"> + <td>a</td> + <td>b</td> + <td>c</td> + </tr> + <tr class="even"> + <td>1</td> + <td>2</td> + <td>3</td> + </tr> + </table> + <h3>A header after the table</h3> +--- +in: | + |_. a|_. b|_. c| + |1|2|3| +out: |- + <table> + <tr class="odd"> + <th>a</th> + <th>b</th> + <th>c</th> + </tr> + <tr class="even"> + <td>1</td> + <td>2</td> + <td>3</td> + </tr> + </table> +--- +in: |- + |This|is|a|simple|table| + |This|is|a|simple|row| +out: |- + <table> + <tr class="odd"> + <td>This</td> + <td>is</td> + <td>a</td> + <td>simple</td> + <td>table</td> + </tr> + <tr class="even"> + <td>This</td> + <td>is</td> + <td>a</td> + <td>simple</td> + <td>row</td> + </tr> + </table> +--- +in: |- + asdf + This is a simple table with tabs + This is a simple row +out: |- + asdf + <table> + <tr class="odd"> + <td>This</td> + <td>is</td> + <td>a</td> + <td>simple</td> + <td>table with tabs</td> + </tr> + <tr class="even"> + <td>This</td> + <td>is</td> + <td>a</td> + <td>simple</td> + <td>row</td> + </tr> + </table> +--- +in: "\ta\tb\tc\t\r\n\ta\tb\tc\t\r\n" +out: |- + <table> + <tr class="odd"> + <td>a</td> + <td>b</td> + <td>c</td> + </tr> + <tr class="even"> + <td>a</td> + <td>b</td> + <td>c</td> + </tr> + </table> +--- +in: |- + table{border:1px solid black}. + |This|is|a|row| + |This|is|a|row| +out: |- + <table style="border:1px solid black;"> + <tr class="odd"> + <td>This</td> + <td>is</td> + <td>a</td> + <td>row</td> + </tr> + <tr class="even"> + <td>This</td> + <td>is</td> + <td>a</td> + <td>row</td> + </tr> + </table> +--- +in: '{background:#ddd}. |This|is|a|row|' +out: |- + <table> + <tr style="background:#ddd;" class="odd"> + <td>This</td> + <td>is</td> + <td>a</td> + <td>row</td> + </tr> + </table> +--- +in: |- + |a|b|c| + | |2|3| +out: |- + <table> + <tr class="odd"> + <td>a</td> + <td>b</td> + <td>c</td> + </tr> + <tr class="even"> + <td> </td> + <td>2</td> + <td>3</td> + </tr> + </table> +--- +in: |- + table{width: 200px; border:2px solid gray;}. + |_=. Alignment| + |=. centered| + |=(. a bit right| + |=). a bit left| + |>). almost right| + |<(. almost left| + |>. right| + |<. left| +out: |- + <table style="width: 200px; border:2px solid gray;"> + <tr class="odd"> + <th style="text-align:center;">Alignment</th> + </tr> + <tr class="even"> + <td style="text-align:center;">centered</td> + </tr> + <tr class="odd"> + <td style="padding-left:1em;text-align:center;">a bit right</td> + </tr> + <tr class="even"> + <td style="padding-right:1em;text-align:center;">a bit left</td> + </tr> + <tr class="odd"> + <td style="padding-right:1em;text-align:right;">almost right</td> + </tr> + <tr class="even"> + <td style="padding-left:1em;text-align:left;">almost left</td> + </tr> + <tr class="odd"> + <td style="text-align:right;">right</td> + </tr> + <tr class="even"> + <td style="text-align:left;">left</td> + </tr> + </table> +--- +in: |- + |{background:#ddd}. Cell with gray background| + |\2. Cell spanning 2 columns| + |/3. Cell spanning 3 rows| + |>. Right-aligned cell| +out: |- + <table> + <tr class="odd"> + <td style="background:#ddd;">Cell with gray background</td> + </tr> + <tr class="even"> + <td colspan="2">Cell spanning 2 columns</td> + </tr> + <tr class="odd"> + <td rowspan="3">Cell spanning 3 rows</td> + </tr> + <tr class="even"> + <td style="text-align:right;">Right-aligned cell</td> + </tr> + </table> +--- +in: | + {background:#ddd}. |S|Target|Complete|App|Milestone| + |!/i/g.gif!|11/29/04|11/29/04|011|XML spec complete (KH is on schedule)| + |!/i/g.gif!|11/22/04|11/22/04|070|Dialog pass 1 builds an index file| + |!/i/g.gif!|11/24/04|11/24/04|070|Dialog pass 2 98% complete| + |!/i/g.gif!|11/30/04|11/30/04|070|Feature complete. Passes end-to-end smoke test.| + |!/i/w.gif!|12/02/04| |011|Dialog pass 1 and 2 complete (98+%)| + |!/i/w.gif!|12/03/04| |081|Feature complete| +out: |- + <table> + <tr style="background:#ddd;" class="odd"> + <td>S</td> + <td>Target</td> + <td>Complete</td> + <td>App</td> + <td>Milestone</td> + </tr> + <tr class="even"> + <td><img src="/i/g.gif" alt="" /></td> + <td>11/29/04</td> + <td>11/29/04</td> + <td>011</td> + <td><span class="caps">XML</span> spec complete (KH is on schedule)</td> + </tr> + <tr class="odd"> + <td><img src="/i/g.gif" alt="" /></td> + <td>11/22/04</td> + <td>11/22/04</td> + <td>070</td> + <td>Dialog pass 1 builds an index file</td> + </tr> + <tr class="even"> + <td><img src="/i/g.gif" alt="" /></td> + <td>11/24/04</td> + <td>11/24/04</td> + <td>070</td> + <td>Dialog pass 2 98% complete</td> + </tr> + <tr class="odd"> + <td><img src="/i/g.gif" alt="" /></td> + <td>11/30/04</td> + <td>11/30/04</td> + <td>070</td> + <td>Feature complete. Passes end-to-end smoke test.</td> + </tr> + <tr class="even"> + <td><img src="/i/w.gif" alt="" /></td> + <td>12/02/04</td> + <td> </td> + <td>011</td> + <td>Dialog pass 1 and 2 complete (98+%)</td> + </tr> + <tr class="odd"> + <td><img src="/i/w.gif" alt="" /></td> + <td>12/03/04</td> + <td> </td> + <td>081</td> + <td>Feature complete</td> + </tr> + </table> +--- +name: combined table header and colspan +in: |- + table(my_class). + |_\2. a |_. b |_. c | + | 1 | 2 | 3 | 4 | +out: |- + <table class="my_class"> + <tr class="odd"> + <th colspan="2">a </th> + <th>b </th> + <th>c </th> + </tr> + <tr class="even"> + <td> 1 </td> + <td> 2 </td> + <td> 3 </td> + <td> 4 </td> + </tr> + </table> +--- +name: two adjacent tables +in: |- + |a|b|c| + + |1|2|3| +out: |- + <table> + <tr class="odd"> + <td>a</td> + <td>b</td> + <td>c</td> + </tr> + </table> + <table> + <tr class="odd"> + <td>1</td> + <td>2</td> + <td>3</td> + </tr> + </table> +--- +name: links in tables +in: | + |{color:red}. a|b|[cute -> http://zooborns.com]| + |1|2|[scary -> http://www.cuteoverlord.blogspot.com]| +out: |- + <table> + <tr class="odd"> + <td style="color:red;">a</td> + <td>b</td> + <td><a href="http://zooborns.com">cute</a></td> + </tr> + <tr class="even"> + <td>1</td> + <td>2</td> + <td><a href="http://www.cuteoverlord.blogspot.com">scary</a></td> + </tr> + </table> + diff --git a/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/textism.yml b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/textism.yml new file mode 100644 index 0000000000000000000000000000000000000000..2d7133a97027da3412ca8323360768867120e89f --- /dev/null +++ b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/textism.yml @@ -0,0 +1,439 @@ +--- +name: header one +in: h1. Header 1 +out: <h1 class="first">Header 1</h1> +latex: \section*{Header 1}\n\n +--- +name: header two +in: h2. Header 2 +out: <h2 class="first">Header 2</h2> +latex: \subsection*{Header 2}\n\n +--- +name: header three +in: h3. Header 3 +out: <h3>Header 3</h3> +latex: \subsubsection*{Header 3}\n\n +--- +name: blockquote +in: |- + Any old text. + + bq. A block quotation. + + Any old text. + +out: |- + <p>Any old text.</p> + <blockquote> + <p>A block quotation.</p> + </blockquote> + <p>Any old text.</p> + +latex: |+ + Any old text. + + \begin{quotation} + A block quotation. + + \end{quotation} + + Any old text. + +--- +in: |- + # A first item + # A second item + # A third item + # A fourth item +out: |- + <ol> + <li>A first item</li> + <li>A second item</li> + <li>A third item</li> + <li>A fourth item</li> + </ol> +latex: |+ + \begin{enumerate} + \item A first item + \item A second item + \item A third item + \item A fourth item + \end{enumerate} + +--- +in: |- + * A first item + * A second item + * A third item + * A fourth item + +out: |- + <ul> + <li>A first item</li> + <li>A second item</li> + <li>A third item</li> + <li>A fourth item</li> + </ul> +latex: |+ + \begin{itemize} + \item A first item + \item A second item + \item A third item + \item A fourth item + \end{itemize} + +--- +in: _a phrase_ +out: <p><em>a phrase</em></p> +latex: "\\emph{a phrase}\n\n" +--- +in: __a phrase__ +out: <p><i>a phrase</i></p> +latex: "\\emph{a phrase}\n\n" +--- +in: '*a phrase*' +out: <p><strong>a phrase</strong></p> +latex: "\\textbf{a phrase}\n\n" +--- +in: '**a phrase**' +out: <p><b>a phrase</b></p> +latex: "\\textbf{a phrase}\n\n" +--- +in: Nabokov's ??Pnin?? +out: <p>Nabokov’s <cite>Pnin</cite></p> +latex: "Nabokov's \\begin{quote}Pnin\\end{quote}\n\n" +--- +name: del part of word +in: 'A very -extra- ordinary day.' +out: "<p>A very <del>extra</del> ordinary day.</p>" +latex: "A very \\sout{extra}ordinary day.\n\n" +--- +name: del part of word that contains a hyphen +in: 'An -extra-extra- ordinary day.' +out: <p>An <del>extra-extra</del> ordinary day.</p> +latex: "An \\sout{extra-extra}ordinary day.\n\n" +--- +name: del a phrase +in: 'Delete -a phrase- this way.' +out: <p>Delete <del>a phrase</del> this way.</p> +latex: "Delete \\sout{a phrase} this way.\n\n" +--- +name: del a phrase that contains hyphens +in: 'Delete -a no-nonsense phrase- this way.' +out: <p>Delete <del>a no-nonsense phrase</del> this way.</p> +latex: "Delete \\sout{a no-nonsense phrase} this way.\n\n" +--- +in: +a phrase+ +out: <p><ins>a phrase</ins></p> +latex: "\\underline{a phrase}\n\n" +--- +in: ^a phrase^ +out: <p><sup>a phrase</sup></p> +latex: "\\ensuremath{^\\textrm{a phrase}}\n\n" +--- +in: ~a phrase~ +out: <p><sub>a phrase</sub></p> +--- +in: '%(myclass)SPAN%' +out: <p><span class="myclass"><span class="caps">SPAN</span></span></p> +no_span_caps_html: <p><span class="myclass">SPAN</span></p> +--- +in: '%{color:red}red%' +out: <p><span style="color:red;">red</span></p> +--- +in: _(big)red_ +out: <p><em class="big">red</em></p> +--- +in: p(bob). A paragraph +out: <p class="bob">A paragraph</p> +--- +in: p{color:#ddd}. A paragraph +out: <p style="color:#ddd;">A paragraph</p> +--- +in: h2()>. right-aligned header2, indented 1em both side +out: <h2 style="padding-left:1em;padding-right:1em;text-align:right;" class="first">right-aligned header2, indented 1em both side</h2> +--- +in: h3=. centered header +out: <h3 style="text-align:center;">centered header</h3> +--- +in: |- + table{border:1px solid black}. + |This|is|a|row| + |This|is|a|row| +out: |- + <table style="border:1px solid black;"> + <tr class="odd"> + <td>This</td> + <td>is</td> + <td>a</td> + <td>row</td> + </tr> + <tr class="even"> + <td>This</td> + <td>is</td> + <td>a</td> + <td>row</td> + </tr> + </table> +--- +in: '{background:#ddd}. |This|is|a|row|' +out: |- + <table> + <tr style="background:#ddd;" class="odd"> + <td>This</td> + <td>is</td> + <td>a</td> + <td>row</td> + </tr> + </table> +--- +in: |- + |{background:#ddd}. Cell with gray background| + |\2. Cell spanning 2 columns| + |/3. Cell spanning 3 rows| + |>. Right-aligned cell| +out: |- + <table> + <tr class="odd"> + <td style="background:#ddd;">Cell with gray background</td> + </tr> + <tr class="even"> + <td colspan="2">Cell spanning 2 columns</td> + </tr> + <tr class="odd"> + <td rowspan="3">Cell spanning 3 rows</td> + </tr> + <tr class="even"> + <td style="text-align:right;">Right-aligned cell</td> + </tr> + </table> +--- +name: basics +in: |- + h2{color:green}. This is a title + + h3. This is a subhead + + p{color:red}. This is some text of dubious character. Isn't the use of "quotes" just lazy writing -- and theft of 'intellectual property' besides? I think the time has come to see a block quote. + + bq. This is a block quote. I'll admit it's not the most exciting block quote ever devised. + + Simple list: + + # one + # two + # three + + Multi-level list: + + # one + ## aye + ## bee + ## see + # two + ## x + ## y + # three + +out: |- + <h2 style="color:green;" class="first">This is a title</h2> + <h3>This is a subhead</h3> + <p style="color:red;">This is some text of dubious character. Isn’t the use of “quotes” just lazy writing — and theft of ‘intellectual property’ besides? I think the time has come to see a block quote.</p> + <blockquote> + <p>This is a block quote. I’ll admit it’s not the most exciting block quote ever devised.</p> + </blockquote> + <p>Simple list:</p> + <ol> + <li>one</li> + <li>two</li> + <li>three</li> + </ol> + <p>Multi-level list:</p> + <ol> + <li>one + <ol> + <li>aye</li> + <li>bee</li> + <li>see</li> + </ol></li> + <li>two + <ol> + <li>x</li> + <li>y</li> + </ol></li> + <li>three</li> + </ol> +--- +name: tougher stuff +in: |- + + Multi-level list: + + # one + ## aye + ## bee + ## see + # two + ## x + ## y + # three + + Mixed list: + + * Point one + * Point two + ## Step 1 + ## Step 2 + ## Step 3 + * Point three + ** Sub point 1 + ** Sub point 2 + + [This is a link -> http://www.textism.com] + +out: |- + <p>Multi-level list:</p> + <ol> + <li>one + <ol> + <li>aye</li> + <li>bee</li> + <li>see</li> + </ol></li> + <li>two + <ol> + <li>x</li> + <li>y</li> + </ol></li> + <li>three</li> + </ol> + <p>Mixed list:</p> + <ul> + <li>Point one</li> + <li>Point two + <ol> + <li>Step 1</li> + <li>Step 2</li> + <li>Step 3</li> + </ol></li> + <li>Point three + <ul> + <li>Sub point 1</li> + <li>Sub point 2</li> + </ul></li> + </ul> + <p><a href="http://www.textism.com">This is a link</a></p> +--- +name: table +in: |- + table{border:1px solid black}. + |_. this|_. is|_. a|_. header| + <{background:gray}. |\2. this is|{background:red;width:200px}. a|^<>{height:200px}. row| + |this|<>{padding:10px}. is|^. another|(bob#bob). row| +out: |- + <table style="border:1px solid black;"> + <tr class="odd"> + <th>this</th> + <th>is</th> + <th>a</th> + <th>header</th> + </tr> + <tr style="text-align:left;background:gray;" class="even"> + <td colspan="2">this is</td> + <td style="background:red;width:200px;">a</td> + <td style="vertical-align:top;text-align:justify;height:200px;">row</td> + </tr> + <tr class="odd"> + <td>this</td> + <td style="text-align:justify;padding:10px;">is</td> + <td style="vertical-align:top;">another</td> + <td class="bob">row</td> + </tr> + </table> +--- +in: |- + An image: + + !/common/textist.gif(optional alt text)! + + # Librarians rule + # Yes they do + # But you knew that + + Some more text of dubious character. Here is a noisome string of CAPITAL letters. Here is something we want to _emphasize_. + That was a linebreak. And something to indicate *strength*. Of course I could use <em>my own HTML tags</em> if I <strong>felt</strong> like it. +out: |- + <p>An image:</p> + <p><img src="/common/textist.gif" title="optional alt text" alt="optional alt text" /></p> + <ol> + <li>Librarians rule</li> + <li>Yes they do</li> + <li>But you knew that</li> + </ol> + <p>Some more text of dubious character. Here is a noisome string of <span class="caps">CAPITAL</span> letters. Here is something we want to <em>emphasize</em>.<br /> + That was a linebreak. And something to indicate <strong>strength</strong>. Of course I could use <em>my own <span class="caps">HTML</span> tags</em> if I <strong>felt</strong> like it.</p> +--- +name: code +in: |- + h3. Coding + + This <code>is some code, "isn't it"</code>. Watch those quote marks! Now for some preformatted text: + + <code> + $text = str_replace("<p>%::%</p>","",$text); + $text = str_replace("%::%</p>","",$text); + $text = str_replace("%::%","",$text); + </code> + + This isn't code. +out: |- + <h3>Coding</h3> + <p>This <code>is some code, "isn't it"</code>. Watch those quote marks! Now for some preformatted text:</p> + <pre><code> $text = str_replace("<p>%::%</p>","",$text); + $text = str_replace("%::%</p>","",$text); + $text = str_replace("%::%","",$text); + </code></pre> + <p>This isn’t code.</p> +--- +name: hard break +in: |- + trivial + break + + next +out: |- + <p>trivial<br /> + break</p> + <p>next</p> +--- +name: normal paragraphs +in: |- + trivial + + paragraphs +out: |- + <p>trivial</p> + <p>paragraphs</p> +--- +name: hard break in a list +in: |- + * first line + * second + line + * third line +out: |- + <ul> + <li>first line</li> + <li>second<br /> + line</li> + <li>third line</li> + </ul> +--- +name: copyright symbol at line start +in: "(C) copyright conversion (C) test." +out: "<p>© copyright conversion © test.</p>" +--- +name: force soft breaks in really long words +in: ohmygodthisisareallyreallylongwordwhydontilikespacesyoumightbeaskingyourself +out: "<p>ohmygodthisisareallyreallylong<wbr/><span class='break'> </span>wordwhydontilikespacesyoumight<wbr/><span class='break'> </span>beaskingyourself</p>" + diff --git a/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/wiki.yml b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/wiki.yml new file mode 100644 index 0000000000000000000000000000000000000000..c6a53a8900a0f2cb6e974ec741727b655675522c --- /dev/null +++ b/vendor/gems/riseuplabs-greencloth-0.1/test/fixtures/wiki.yml @@ -0,0 +1,9 @@ +--- +name: a left aligned image (<p> should have class 'left') +in: |- + !</assets/5/rain.jpg! +out: |- + <p style="float:left;" class="left"><img src="/assets/5/rain.jpg" alt="" /></p> +--- +in: '!>/image.gif! right-aligned image' +out: <p style="float:right;" class="right"><img src="/image.gif" alt="" /> right-aligned image</p> diff --git a/vendor/gems/riseuplabs-greencloth-0.1/test/lite_mode_test.rb b/vendor/gems/riseuplabs-greencloth-0.1/test/lite_mode_test.rb new file mode 100644 index 0000000000000000000000000000000000000000..f57d9b099837c3fbee8bdb750d88cbddb115912a --- /dev/null +++ b/vendor/gems/riseuplabs-greencloth-0.1/test/lite_mode_test.rb @@ -0,0 +1,16 @@ +require 'rubygems' +require 'test/unit' + +test_dir = File.dirname(File.expand_path(__FILE__)) +require test_dir + '/../lib/greencloth.rb' + +class TestLiteMode < Test::Unit::TestCase + + def setup + end + + def test_filter_html + html = GreenCloth.new("aaa <script>alert('hi')</script> aa", 'page', [:lite_mode]).to_html + assert_equal "aaa <script>alert('hi')</script> aa", html + end +end diff --git a/vendor/gems/riseuplabs-greencloth-0.1/test/markup_test.rb b/vendor/gems/riseuplabs-greencloth-0.1/test/markup_test.rb new file mode 100644 index 0000000000000000000000000000000000000000..de5dccdcf16a0273f1b990ec3a9beaf50289c1fc --- /dev/null +++ b/vendor/gems/riseuplabs-greencloth-0.1/test/markup_test.rb @@ -0,0 +1,79 @@ +require 'rubygems' +require 'ruby-debug' +require 'yaml' +require 'test/unit' + +test_dir = File.dirname(File.expand_path(__FILE__)) +require test_dir + '/../lib/greencloth.rb' + +SINGLE_FILE_OVERRIDE = if ARGV[0] and ARGV[0] !~ /\.rb/ + ARGV[0] +else + nil +end + +class TestMarkup < Test::Unit::TestCase + + def setup + files = SINGLE_FILE_OVERRIDE || Dir[File.dirname(__FILE__) + "/fixtures/*.yml"] + @fixtures = {} + files.each do |testfile| + begin + YAML::load_documents( File.open( testfile ) ) do |doc| + @fixtures[ File.basename(testfile) ] ||= [] + @fixtures[ File.basename(testfile) ] << doc + end + rescue SyntaxError + puts "Failed to load #{testfile}" + raise + end + end + @special = ['sections.yml', 'outline.yml'] + @markup_fixtures = @fixtures.reject{|key,value| @special.include? key} + end + + def test_general_markup + @markup_fixtures.each do |filename, docs| + docs.each do |doc| + assert_markup filename, doc, GreenCloth.new(doc['in']).to_html + end + end + end + + def test_outline + return unless @fixtures['outline.yml'] + @fixtures['outline.yml'].each do |doc| + assert_markup('outline.yml', doc, GreenCloth.new(doc['in'], '', [:outline]).to_html) + end + end + + #def test_sections + # return unless @fixtures['sections.yml'] + # @fixtures['sections.yml'].each do |doc| + # greencloth = GreenCloth.new( doc['in'] ) + # greencloth.wrap_section_html = true + # assert_markup('sections.yml', doc, greencloth.to_html) + # end + #end + + protected + + def assert_markup(filename, doc, html) + in_markup = doc['in'] + out_markup = doc['out'] || doc['html'] + return unless in_markup and out_markup + html.gsub!( /\n+/, "\n" ) + out_markup.gsub!( /\n+/, "\n" ) + if html == out_markup + putc "." + else + puts "\n------- #{filename} failed -------" + puts "---- IN ----"; p in_markup + puts "---- OUT ----"; puts html + puts "---- EXPECTED ----"; puts out_markup + puts "" + end + end +end + + diff --git a/vendor/gems/riseuplabs-greencloth-0.1/test/outline_test.rb b/vendor/gems/riseuplabs-greencloth-0.1/test/outline_test.rb new file mode 100644 index 0000000000000000000000000000000000000000..0fcf073294a1a18326ecb2acf58b825e2f185ce2 --- /dev/null +++ b/vendor/gems/riseuplabs-greencloth-0.1/test/outline_test.rb @@ -0,0 +1,244 @@ +require 'test/unit' +require 'rubygems' +require 'ruby-debug' +require 'yaml' + +test_dir = File.dirname(File.expand_path(__FILE__)) +require test_dir + '/../lib/greencloth.rb' + +class TestHeadings < Test::Unit::TestCase + + def setup + testfile = File.dirname(__FILE__) + '/fixtures/outline.yml' + @fixtures = {} + YAML::load_documents( File.open( testfile ) ) do |doc| + key = doc.delete("name") + @fixtures[key] = doc + end + end + + def test_successive_heading + greencloth = GreenCloth.new( in_texts(:fruity_outline) ) + tree = greencloth.green_tree + + assert_equal 'vegetables', tree.find('fruits').successor.name + assert_equal 'pears', tree.find('tasty-apples').successor.name + assert_equal 'vegetables', tree.find('pears').successor.name + end + + def test_badly_organized_successive_heading + greencloth = GreenCloth.new( in_texts(:badly_organized_fruits) ) + tree = greencloth.green_tree + + assert_equal 'vegetables', tree.find('fruits').successor.name + assert_equal 'tasty-apples', tree.find('green-apples').successor.name + assert_equal 'pears', tree.find('tasty-apples').successor.name + end + + def test_get_text + greencloth = GreenCloth.new( in_texts(:fruity_outline) ) + tree = greencloth.green_tree + + assert_equal "h2. Tasty Apples\n\nh3. Green\n\nh3. Red\n\n", + tree.find('tasty-apples').markup + + assert_equal "h1. Vegetables\n\nh2. Turnips\n\nh2. Green Beans", + tree.find('vegetables').markup + + assert_equal "h2. Pears\n\n", tree.find('pears').markup + end + + def test_weird_text + greencloth = GreenCloth.new( in_texts(:weird_chars) ) + tree = greencloth.green_tree + + assert_equal "h1. i eat 'food'\n\n", tree.find('i-eat-food').markup + end + + def test_get_setext_style_headings + greencloth = GreenCloth.new( in_texts(:setext_trees) ) + tree = greencloth.green_tree + + assert_equal "Evergreens\n==========\n\nh3. Cedar\n\nh3. Redwood\n\nh3. Fir\n\n", + tree.find('evergreens').markup + + assert_equal "Oaks\n----\n\nh3. White Oak\n\nh3. Red Oak", + tree.find('oaks').markup + + assert_equal "h3. Fir\n\n", tree.find('fir').markup + end + + def test_duplicate_names + greencloth = GreenCloth.new( in_texts(:double_trouble) ) + tree = greencloth.green_tree + + assert_equal "h1. Title\n\nh3. Under first\n\n", tree.find('title').markup + assert_equal "h1. Title\n\nh3. Under second", tree.find('title_2').markup + end + + def test_set_text + greencloth = GreenCloth.new( in_texts(:fruity_outline) ) + tree = greencloth.green_tree + + assert_equal "[[toc]]\n\nh1. Fruits\n\nxxxxx\n\nh2. Pears\n\nh1. Vegetables\n\nh2. Turnips\n\nh2. Green Beans", tree.find('tasty-apples').sub_markup('xxxxx') + + assert_equal "[[toc]]\n\nh1. Fruits\n\nh2. Oranges\n\nooooo\n\nh2. Pears\n\nh1. Vegetables\n\nh2. Turnips\n\nh2. Green Beans", tree.find('tasty-apples').sub_markup("h2. Oranges\n\nooooo") + end + + def test_repeatedly_set_text + greencloth = GreenCloth.new( in_texts(:fruity_outline) ) + tree = greencloth.green_tree + + markup = tree.find('red').sub_markup("h3. Red\n\n") + assert_equal "[[toc]]\n\nh1. Fruits\n\nh2. Tasty Apples\n\nh3. Green\n\nh3. Red\n\nh2. Pears\n\nh1. Vegetables\n\nh2. Turnips\n\nh2. Green Beans", markup + + tree = GreenCloth.new(markup).green_tree + markup = tree.find('red').sub_markup("h3. Red\n\n") + assert_equal "[[toc]]\n\nh1. Fruits\n\nh2. Tasty Apples\n\nh3. Green\n\nh3. Red\n\nh2. Pears\n\nh1. Vegetables\n\nh2. Turnips\n\nh2. Green Beans", markup + + tree = GreenCloth.new(markup).green_tree + markup = tree.find('red').sub_markup("h3. Red\n\n") + assert_equal "[[toc]]\n\nh1. Fruits\n\nh2. Tasty Apples\n\nh3. Green\n\nh3. Red\n\nh2. Pears\n\nh1. Vegetables\n\nh2. Turnips\n\nh2. Green Beans", markup + end + + def test_set_text_leaves_some_trailing_whitespace + greencloth = GreenCloth.new( in_texts(:fruity_outline) ) + tree = greencloth.green_tree + + markup = tree.find('red').sub_markup("h3. Red") + assert_equal "[[toc]]\n\nh1. Fruits\n\nh2. Tasty Apples\n\nh3. Green\n\nh3. Red\n\nh2. Pears\n\nh1. Vegetables\n\nh2. Turnips\n\nh2. Green Beans", markup + end + + def test_multinine_heading + greencloth = GreenCloth.new( in_texts(:multiline_headings) ) + tree = greencloth.green_tree + + assert_equal "h1. section one line one\nline two\n\nsection one text\n\nh2. subsection\nwithout content\n\n", + tree.find('section-one-line-one-line-two').markup + + assert_equal "h1. section two line one\nline two\n\nsection two text", + tree.find('section-two-line-one-line-two').markup + end + + def test_nested_sections + greencloth = GreenCloth.new( in_texts(:weird_and_nested) ) + tree = greencloth.green_tree + + assert_equal "h1. Highest\n\nlower\n-----------\n\nlower text\n\nh2. even lower\n\nh3. lowest\n\nlowest text\n\nh3. lowest and blankest\n\n", + tree.find('highest').markup + + assert_equal "lower\n-----------\n\nlower text\n\n", + tree.find('lower').markup + + assert_equal "h2. even lower\n\nh3. lowest\n\nlowest text\n\nh3. lowest and blankest\n\n", + tree.find('even-lower').markup + + assert_equal "h3. lowest\n\nlowest text\n\n", + tree.find('lowest').markup + + assert_equal "h3. lowest and blankest\n\n", + tree.find('lowest-and-blankest').markup + + assert_equal "high as they get\n=================\n\nh2. underling\n\nunderling text", + tree.find('high-as-they-get').markup + + assert_equal "h2. underling\n\nunderling text", + tree.find('underling').markup + end + + def test_link_with_whitespace_after_first_char + greencloth = GreenCloth.new("[a link->http://example.com]") + assert_equal "<p><a href=\"http://example.com\">a link</a></p>", + greencloth.to_html + end + + def test_anchor_link_with_whitespace_after_first_char + greencloth = GreenCloth.new("[# link]") + assert_equal "<p><a href=\"#link\">link</a></p>", greencloth.to_html + end + + def test_set_text_around_untitled_section + greencloth = GreenCloth.new( in_texts(:untitled_leading_section) ) + tree = greencloth.green_tree + + assert_equal "\nwelcome to our great list of fruits and vegetables\n\nh1. No Fruits\n\nh1. Vegetables\n\nh2. Green Beans", tree.find('fruits').sub_markup('h1. No Fruits') + end + + def test_plain_old_text + greencloth = GreenCloth.new( in_texts(:plain_old_text) ) + tree = greencloth.green_tree + + assert_equal [], tree.section_names + assert_equal greencloth.size - 1, tree.end_index + end + + def test_overdecorated + greencloth = GreenCloth.new( in_texts(:overdecorated) ) + tree = greencloth.green_tree + + section_markup_map = { + 'emphasis' => "h2. _emphasis_\n\n", + 'italicized' => "__italicized__\n--------------\n\n", + 'strong' => "h2. *strong*\n\n", + 'bold' => "**bold**\n--------\n\n", + 'citation' => "h2. ??citation??\n\n", + 'deleted-text' => "-deleted text-\n--------------\n\n", + 'inserted-text' => "h2. +inserted text+\n\n", + 'superscript' => "^superscript^\n-------------\n\n", + 'subscript' => "h2. ~subscript~\n\n", + 'code' => "@code@\n------\n\n", + 'table' => "h2. [-table-]\n\n", + 'heading-anchor' => "[# Heading anchor -> head_anchor #]\n-----------------------------------\n\n", + 'anchor-within-heading' => "h2. Anchor _within_ [# heading -> head_anchor #]\n\n", + 'dots' => "Dots ...\n--------" + } + + section_markup_map.each do |section, markup| + assert_equal markup, tree.find(section).markup + end + end + + def test_leading_and_trailing_whitespace + greencloth = GreenCloth.new( in_texts(:leading_and_trailing_whitespace) ) + tree = greencloth.green_tree + + assert_equal "Clearly a Section\n===\n\n still a section\n\n---\nmore text\n\n<code>\n coding\n\n not a section\n\n ---\n more text here\n</code>", + tree.find('clearly-a-section').markup + + assert_equal " still a section\n\n---\nmore text\n\n<code>\n coding\n\n not a section\n\n ---\n more text here\n</code>", + tree.find('still-a-section').markup + + assert_nil tree.find('not-a-section') + end + + def test_code_block_weirdness + greencloth = GreenCloth.new( in_texts(:code_block_weirdness) ) + tree = greencloth.green_tree + + assert_equal ['real-stuff'], tree.section_names + + + assert_equal "real stuff\n----\n\n<code>\n\na.. b\n-----\n\naa... bb\n-----\n\n</code>", + tree.find('real-stuff').markup + + assert_nil tree.find('aa-bb') + assert_nil tree.find('a-b') + end + + + protected + + def in_texts(name) + name = name.to_s.gsub('_',' ') + text = (@fixtures[name]||{})['in'] + assert_not_nil text, 'could not find fixture data "%s"' % name + return text + end + +end + + + + + +