diff --git a/app/controllers/articles_controller.rb b/app/controllers/articles_controller.rb index 3cd53ef7d76..959abbe8d61 100644 --- a/app/controllers/articles_controller.rb +++ b/app/controllers/articles_controller.rb @@ -8,12 +8,17 @@ class ArticlesController < ApplicationController def index @articles = list_articles @articles = @articles.tagged_with(params[:tag]) if params[:tag] - render layout: 'welcome' + number_per_page = @articles.page(1).limit_value + @atom_articles = list_recent_articles(number_per_page) + respond_to do |format| + format.html { render layout: 'welcome' } + format.atom + end end def show @mentor = @article.user - @recent_articles = list_recent_articles + @recent_articles = list_recent_articles(10) if @article.published? || admin_or_mentor_login? render layout: 'welcome' else @@ -66,9 +71,9 @@ def list_articles admin_or_mentor_login? ? articles : articles.where(wip: false) end - def list_recent_articles + def list_recent_articles(number) Article.with_attached_thumbnail.includes(user: { avatar_attachment: :blob }) - .where(wip: false).order(published_at: :desc).limit(10) + .where(wip: false).order(published_at: :desc).limit(number) end def article_params diff --git a/app/javascript/stylesheets/application/blocks/footer/_footer-nav.sass b/app/javascript/stylesheets/application/blocks/footer/_footer-nav.sass index 474085f31ec..0dff1a7e82f 100644 --- a/app/javascript/stylesheets/application/blocks/footer/_footer-nav.sass +++ b/app/javascript/stylesheets/application/blocks/footer/_footer-nav.sass @@ -2,6 +2,7 @@ display: flex line-height: 1.4 flex-wrap: wrap + align-items: center +media-breakpoint-up(md) font-size: .8125rem justify-content: center diff --git a/app/javascript/stylesheets/shared/blocks/_not-logged-in-footer.sass b/app/javascript/stylesheets/shared/blocks/_not-logged-in-footer.sass index aa6ee20cea4..b54b080eb46 100644 --- a/app/javascript/stylesheets/shared/blocks/_not-logged-in-footer.sass +++ b/app/javascript/stylesheets/shared/blocks/_not-logged-in-footer.sass @@ -13,6 +13,7 @@ +media-breakpoint-up(lg) gap: 1rem justify-content: center + align-items: center +media-breakpoint-up(md) display: flex flex-wrap: wrap @@ -44,6 +45,12 @@ align-items: center padding-inline: 1rem +size(100% 2.75rem) + i + font-size: .75em + position: relative + top: -.0625em + i:first-child + margin-right: .375em body.is-welcome & color: var(--default-text) diff --git a/app/views/application/footer/_footer.html.slim b/app/views/application/footer/_footer.html.slim index 1fa2f1feeec..75f0b364694 100644 --- a/app/views/application/footer/_footer.html.slim +++ b/app/views/application/footer/_footer.html.slim @@ -52,7 +52,9 @@ footer.footer li.footer-nav__item = link_to 'https://fbc-stack.vercel.app/', class: 'footer-nav__item-link', target: '_blank', rel: 'noopener' do | FBC Stack - + li.footer-nav__item + = link_to '/articles.atom', class: 'a-button is-sm is-secondary is-icon', target: '_blank', rel: 'noopener', title: 'フィヨルドブートキャンプブログフィード' do + i.fa-solid.fa-rss small.footer__copyright i.fa-regular.fa-copyright = link_to 'Lokka Inc.', 'https://lokka.jp', class: 'footer__copyright-link' diff --git a/app/views/articles/index.atom.builder b/app/views/articles/index.atom.builder new file mode 100644 index 00000000000..49664f69317 --- /dev/null +++ b/app/views/articles/index.atom.builder @@ -0,0 +1,17 @@ +atom_feed do |feed| + feed.title("ブログ | FJORD BOOT CAMP(フィヨルドブートキャンプ)") + feed.updated(@atom_articles.first.created_at) + @atom_articles.each do |article| + feed.entry(article) do |entry| + entry.title(article.title) + summary_html = md2html(article.summary) + entry.summary(summary_html, type: 'html') + body_html = md2html(article.body) + entry.content(body_html, type: 'html') + + entry.author do |author| + author.name(article.user.login_name) + end + end + end +end diff --git a/app/views/articles/index.html.slim b/app/views/articles/index.html.slim index 84991d1ce01..8dd6ac0f9a7 100644 --- a/app/views/articles/index.html.slim +++ b/app/views/articles/index.html.slim @@ -1,6 +1,7 @@ - title 'ブログ' - set_meta_tags(site: 'FJORD BOOT CAMP(フィヨルドブートキャンプ)', description: 'オンラインプログラミングフィヨルドブートキャンプのブログ記事一覧ページです。') += auto_discovery_link_tag(:atom, 'https://bootcamp.fjord.jp/articles.atom', { title: 'Atom Feed' }) = render '/head/fontawsome' .welcome-page-header diff --git a/app/views/layouts/application.html.slim b/app/views/layouts/application.html.slim index 7ab51f071c1..ec72c98e69a 100644 --- a/app/views/layouts/application.html.slim +++ b/app/views/layouts/application.html.slim @@ -24,6 +24,7 @@ html.is-application lang='ja' = stylesheet_link_tag 'https://cdn.jsdelivr.net/npm/yakuhanjp@3.2.0/dist/css/yakuhanjp_s-narrow.min.css', media: 'all' = stylesheet_link_tag 'https://fonts.googleapis.com/css2?family=Roboto:wght@400;700;900&display=swap', media: 'all' = render '/head/fontawsome' + link(rel='alternate' type='application/atom+xml' title='フィヨルドブートキャンプブログ' href='/articles.atom') = content_for(:head_last) if content_for?(:head_last) body.is-application#body(class="#{body_class}") = render 'google_analytics' if Rails.env.production? && !staging? diff --git a/app/views/layouts/welcome.html.slim b/app/views/layouts/welcome.html.slim index 3d99eb5cc51..07a71121214 100644 --- a/app/views/layouts/welcome.html.slim +++ b/app/views/layouts/welcome.html.slim @@ -21,9 +21,10 @@ html.is-application lang='ja' = stylesheet_link_tag 'https://fonts.googleapis.com/css?family=Source+Code+Pro', media: 'all' = stylesheet_link_tag 'https://cdn.jsdelivr.net/npm/yakuhanjp@3.2.0/dist/css/yakuhanjp_s-narrow.min.css', media: 'all' = render '/head/fontawsome' + link(rel='alternate' type='application/atom+xml' title='フィヨルドブートキャンプブログ' href='/articles.atom') = content_for(:head_last) if content_for?(:head_last) - if defined?(@article) && @article.wip? - meta name="robots" content="none" + meta(name="robots" content="none") body.is-welcome#body class="#{body_class}" = render 'google_analytics' if Rails.env.production? && !staging? .wrapper diff --git a/app/views/shared/_not_logged_in_footer.html.slim b/app/views/shared/_not_logged_in_footer.html.slim index b11be7bfdb4..f61adedd610 100644 --- a/app/views/shared/_not_logged_in_footer.html.slim +++ b/app/views/shared/_not_logged_in_footer.html.slim @@ -23,6 +23,9 @@ footer.not-logged-in-footer li.not-logged-in-footer__nav-item = link_to new_comeback_path, class: 'not-logged-in-footer__nav-item-link' do | 休会からの復帰 + li.not-logged-in-footer__nav-item + = link_to '/articles.atom', class: 'a-button is-sm is-secondary is-icon', target: '_blank', rel: 'noopener', title: 'フィヨルドブートキャンプブログフィード' do + i.fa-solid.fa-rss small.not-logged-in-footer-copyright i.fa-regular.fa-copyright span.not-logged-in-footer-copyright__author diff --git a/test/system/articles_test.rb b/test/system/articles_test.rb index e597eb42486..1d1cd2639be 100644 --- a/test/system/articles_test.rb +++ b/test/system/articles_test.rb @@ -381,4 +381,35 @@ class ArticlesTest < ApplicationSystemTestCase assert_selector "a[href='https://b.hatena.ne.jp/entry/s/bootcamp.fjord.jp/articles/#{@article.id}#bbutton']" end end + + test 'items of article shown in atom feed' do + visit_with_auth new_article_url, 'komagata' + + fill_in 'article[title]', with: 'エントリーのタイトル(text)' + fill_in 'article[summary]', with: 'サマリー(HTML)' + fill_in 'article[body]', with: '本文(HTML)' + within '.select-users' do + find('.choices__inner').click + find('#choices--js-choices-single-select-item-choice-6', text: 'mentormentaro').click + end + click_on '公開する' + + visit '/articles.atom' + assert_text 'エントリーのタイトル(text)' + assert_text '<p>サマリー(HTML)</p>' + assert_text '<p>本文(HTML)</p>' + assert_text 'mentormentaro' + end + + test 'WIP article is not shown in atom feed' do + visit_with_auth new_article_url, 'komagata' + + fill_in 'article[title]', with: 'WIPの記事は atom feed に表示されない' + fill_in 'article[body]', with: 'WIPの記事は atom feed に表示されない' + click_on 'WIP' + assert_text '記事をWIPとして保存しました' + + visit '/articles.atom' + assert_no_text 'WIPの記事は atom feed に表示されない' + end end