diff --git a/app/controllers/wiki_pages_controller.rb b/app/controllers/wiki_pages_controller.rb index 2c5a29c54..2d3272e95 100644 --- a/app/controllers/wiki_pages_controller.rb +++ b/app/controllers/wiki_pages_controller.rb @@ -11,7 +11,7 @@ class WikiPagesController < ApplicationController end def edit - @wiki_page = WikiPage.find(params[:id]) + @wiki_page, _ = WikiPage.find_by_id_or_title(params[:id]) respond_with(@wiki_page) end @@ -30,18 +30,16 @@ class WikiPagesController < ApplicationController end def show - if params[:id] =~ /\A\d+\z/ - @wiki_page = WikiPage.find(params[:id]) - else - @wiki_page = WikiPage.titled(params[:id]).first - end + @wiki_page, found_by = WikiPage.find_by_id_or_title(params[:id]) - if @wiki_page.present? - respond_with(@wiki_page) - elsif request.format.html? + if request.format.html? && @wiki_page.blank? && found_by == :title redirect_to show_or_new_wiki_pages_path(title: params[:id]) - else + elsif request.format.html? && @wiki_page.present? && found_by == :id + redirect_to @wiki_page + elsif @wiki_page.blank? raise ActiveRecord::RecordNotFound + else + respond_with(@wiki_page) end end @@ -51,19 +49,19 @@ class WikiPagesController < ApplicationController end def update - @wiki_page = WikiPage.find(params[:id]) + @wiki_page, _ = WikiPage.find_by_id_or_title(params[:id]) @wiki_page.update(wiki_page_params(:update)) respond_with(@wiki_page) end def destroy - @wiki_page = WikiPage.find(params[:id]) + @wiki_page, _ = WikiPage.find_by_id_or_title(params[:id]) @wiki_page.update(is_deleted: true) respond_with(@wiki_page) end def revert - @wiki_page = WikiPage.find(params[:id]) + @wiki_page, _ = WikiPage.find_by_id_or_title(params[:id]) @version = @wiki_page.versions.find(params[:version_id]) @wiki_page.revert_to!(@version) flash[:notice] = "Page was reverted" diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 32e64f6a4..3de57bf14 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -103,13 +103,14 @@ module ApplicationHelper link_to search, posts_path(tags: search) end - def link_to_wiki(text, title) - link_to text, wiki_page_path(title) + def link_to_wiki(text, title = text, **options) + title = "~#{title}" if title =~ /\A\d+\z/ + link_to text, wiki_page_path(title), class: "wiki-link", **options end def link_to_wikis(*wiki_titles, last_word_connector: ", or", **options) links = wiki_titles.map do |title| - link_to title.tr("_", " "), wiki_page_path(title) + link_to_wiki title.tr("_", " "), title end to_sentence(links, **options) diff --git a/app/helpers/tags_helper.rb b/app/helpers/tags_helper.rb index 35fe58b86..cf2ecc9c7 100644 --- a/app/helpers/tags_helper.rb +++ b/app/helpers/tags_helper.rb @@ -6,32 +6,32 @@ module TagsHelper if tag.antecedent_alias html << "

This tag has been aliased to " - html << link_to(tag.antecedent_alias.consequent_name, show_or_new_wiki_pages_path(:title => tag.antecedent_alias.consequent_name)) + html << link_to_wiki(tag.antecedent_alias.consequent_name) html << " (#{link_to_wiki "learn more", "help:tag_aliases"}).

" end if tag.consequent_aliases.present? html << "

The following tags are aliased to this tag: " - html << raw(tag.consequent_aliases.map {|x| link_to(x.antecedent_name, show_or_new_wiki_pages_path(:title => x.antecedent_name))}.join(", ")) + html << raw(tag.consequent_aliases.map {|x| link_to_wiki x.antecedent_name }.join(", ")) html << " (#{link_to_wiki "learn more", "help:tag_aliases"}).

" end automatic_tags = TagImplication.automatic_tags_for([tag.name]) if automatic_tags.present? html << "

This tag automatically adds " - html << raw(automatic_tags.map {|x| link_to(x, show_or_new_wiki_pages_path(:title => x))}.join(", ")) + html << raw(automatic_tags.map {|x| link_to_wiki x, x }.join(", ")) html << " (#{link_to_wiki "learn more", "help:autotags"}).

" end if tag.antecedent_implications.present? html << "

This tag implicates " - html << raw(tag.antecedent_implications.map {|x| link_to(x.consequent_name, show_or_new_wiki_pages_path(:title => x.consequent_name))}.join(", ")) + html << raw(tag.antecedent_implications.map {|x| link_to_wiki x.consequent_name }.join(", ")) html << " (#{link_to_wiki "learn more", "help:tag_implications"}).

" end if tag.consequent_implications.present? html << "

The following tags implicate this tag: " - html << raw(tag.consequent_implications.map {|x| link_to(x.antecedent_name, show_or_new_wiki_pages_path(:title => x.antecedent_name))}.join(", ")) + html << raw(tag.consequent_implications.map {|x| link_to_wiki x.antecedent_name }.join(", ")) html << " (#{link_to_wiki "learn more", "help:tag_implications"}).

" end diff --git a/app/javascript/src/styles/base/030_links.scss b/app/javascript/src/styles/base/030_links.scss index 54632a000..34b709cf6 100644 --- a/app/javascript/src/styles/base/030_links.scss +++ b/app/javascript/src/styles/base/030_links.scss @@ -22,10 +22,6 @@ a.active { font-weight: bold; } -a.wiki-link { - margin-right: 0.3em; -} - a[rel*="external"] { word-break: break-all; } diff --git a/app/javascript/src/styles/specific/posts.scss b/app/javascript/src/styles/specific/posts.scss index 23cf5077d..18f9a520f 100644 --- a/app/javascript/src/styles/specific/posts.scss +++ b/app/javascript/src/styles/specific/posts.scss @@ -275,6 +275,10 @@ div#c-posts { aside#sidebar > section > ul { margin-bottom: 1em; + + a.wiki-link { + margin-right: 0.3em; + } } aside#sidebar > section > ul ul li { diff --git a/app/logical/tag_name_validator.rb b/app/logical/tag_name_validator.rb index 78fc09e66..9cbcecad3 100644 --- a/app/logical/tag_name_validator.rb +++ b/app/logical/tag_name_validator.rb @@ -25,6 +25,8 @@ class TagNameValidator < ActiveModel::EachValidator record.errors[attribute] << "'#{value}' cannot begin with '#{$1}:'" when /\A(#{Tag.categories.regexp}):(.+)\z/i record.errors[attribute] << "'#{value}' cannot begin with '#{$1}:'" + when "new", "search" + record.errors[attribute] << "'#{value}' is a reserved name and cannot be used" when /\A(.+)_\(cosplay\)\z/i tag_name = TagAlias.to_aliased([$1]).first tag = Tag.find_by_name(tag_name) diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb index 06531873a..974a7b4dc 100644 --- a/app/models/wiki_page.rb +++ b/app/models/wiki_page.rb @@ -23,6 +23,14 @@ class WikiPage < ApplicationRecord api_attributes including: [:category_name] module SearchMethods + def find_by_id_or_title(id) + if id =~ /\A\d+\z/ + [find_by_id(id), :id] + else + [find_by_title(normalize_title(id)), :title] + end + end + def titled(title) where(title: normalize_title(title)) end @@ -138,7 +146,7 @@ class WikiPage < ApplicationRecord end def self.normalize_title(title) - title.downcase.gsub(/[[:space:]]+/, "_").gsub(/__/, "_").gsub(/\A_|_\z/, "") + title.downcase.delete_prefix("~").gsub(/[[:space:]]+/, "_").gsub(/__/, "_").gsub(/\A_|_\z/, "") end def normalize_title @@ -235,4 +243,12 @@ class WikiPage < ApplicationRecord def visible? artist.blank? || !artist.is_banned? || CurrentUser.is_builder? end + + def to_param + if title =~ /\A\d+\z/ + "~#{title}" + else + title + end + end end diff --git a/app/presenters/tag_set_presenter.rb b/app/presenters/tag_set_presenter.rb index cd99ba42b..e244c323d 100644 --- a/app/presenters/tag_set_presenter.rb +++ b/app/presenters/tag_set_presenter.rb @@ -113,8 +113,10 @@ class TagSetPresenter < Presenter unless name_only if category == Tag.categories.artist html << %{? } + elsif name =~ /\A\d+\z/ + html << %{? } else - html << %{? } + html << %{? } end if show_extra_links && current_query.present? diff --git a/app/views/dtext_links/index.html.erb b/app/views/dtext_links/index.html.erb index 029371b40..96028ba5c 100644 --- a/app/views/dtext_links/index.html.erb +++ b/app/views/dtext_links/index.html.erb @@ -35,7 +35,7 @@ <% if dtext_link.external_link? %> <%= external_link_to(dtext_link.link_target) %> <% elsif dtext_link.wiki_link? %> - <%= link_to(dtext_link.link_target, show_or_new_wiki_pages_path(title: dtext_link.link_target), class: "tag-type-#{Tag.category_for(dtext_link.link_target)}") %> + <%= link_to_wiki dtext_link.link_target, class: "tag-type-#{Tag.category_for(dtext_link.link_target)}" %> <% end %> <%= link_to("»", dtext_links_path(search: { link_target: dtext_link.link_target })) %> diff --git a/app/views/related_tags/_current_tags.html.erb b/app/views/related_tags/_current_tags.html.erb index aa87e8754..ebdff2521 100644 --- a/app/views/related_tags/_current_tags.html.erb +++ b/app/views/related_tags/_current_tags.html.erb @@ -1,10 +1,10 @@ diff --git a/app/views/related_tags/show.html.erb b/app/views/related_tags/show.html.erb index bb204ddc1..f8d7df9b8 100644 --- a/app/views/related_tags/show.html.erb +++ b/app/views/related_tags/show.html.erb @@ -20,7 +20,7 @@ <% @query.tags_for_html.each do |tag, category| %> - <%= link_to("?", show_or_new_wiki_pages_path(:title => tag)) %> + <%= link_to_wiki "?", tag %> <%= link_to(tag, posts_path(:tags => tag)) %> diff --git a/app/views/tags/index.html.erb b/app/views/tags/index.html.erb index 391166fc3..26012f28c 100644 --- a/app/views/tags/index.html.erb +++ b/app/views/tags/index.html.erb @@ -14,7 +14,7 @@ <%= tag.post_count %> - <%= link_to("?", show_or_new_wiki_pages_path(:title => tag.name)) %> + <%= link_to_wiki "?", tag.name %> <%= link_to(tag.name, posts_path(:tags => tag.name)) %> diff --git a/test/functional/wiki_pages_controller_test.rb b/test/functional/wiki_pages_controller_test.rb index 14022ec5d..0160c2db3 100644 --- a/test/functional/wiki_pages_controller_test.rb +++ b/test/functional/wiki_pages_controller_test.rb @@ -40,13 +40,29 @@ class WikiPagesControllerTest < ActionDispatch::IntegrationTest end end - should "render" do - get wiki_page_path(@wiki_page) + should "redirect to the title for an id" do + get wiki_page_path(@wiki_page.id) + assert_redirected_to wiki_page_path(@wiki_page.title) + + get wiki_page_path(@wiki_page.id), as: :json assert_response :success end + should "distinguish between an id and a title" do + as(@user) { @wiki_page.update(title: "2019") } + + get wiki_page_path("~2019") + assert_response :success + + get wiki_page_path(@wiki_page.id) + assert_redirected_to wiki_page_path("~2019") + + get wiki_page_path("2019") + assert_response 404 + end + should "render for a title" do - get wiki_page_path(:id => @wiki_page.title) + get wiki_page_path(@wiki_page.title) assert_response :success end @@ -64,8 +80,9 @@ class WikiPagesControllerTest < ActionDispatch::IntegrationTest as_user do @wiki_page.update(title: "-aaa") end - get wiki_page_path(:id => @wiki_page.id) - assert_response :success + + get wiki_page_path(@wiki_page.id) + assert_redirected_to wiki_page_path(@wiki_page.title) end end diff --git a/test/unit/post_test.rb b/test/unit/post_test.rb index 3a508d6c2..a648aecd6 100644 --- a/test/unit/post_test.rb +++ b/test/unit/post_test.rb @@ -695,7 +695,7 @@ class PostTest < ActiveSupport::TestCase context "that already exists" do setup do - %W(___ ~foo _foo foo_ foo__bar foo*bar foo,bar foo\abar café 東方).each do |tag| + %W(___ ~foo _foo foo_ foo__bar foo*bar foo,bar foo\abar café 東方 new search).each do |tag| build(:tag, name: tag).save(validate: false) end end @@ -710,6 +710,8 @@ class PostTest < ActiveSupport::TestCase assert_invalid_tag("foo\abar") assert_invalid_tag("café") assert_invalid_tag("東方") + assert_invalid_tag("new") + assert_invalid_tag("search") end end