From 5afee2f344e9f7a1acd29a50bc2281ae815afa9d Mon Sep 17 00:00:00 2001 From: miteruzo Date: Tue, 24 Jun 2025 07:05:21 +0900 Subject: [PATCH] =?UTF-8?q?#45=20=E5=B7=AE=E5=88=86=20API=20=E4=BD=9C?= =?UTF-8?q?=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/Gemfile | 2 + backend/Gemfile.lock | 2 + .../app/controllers/wiki_pages_controller.rb | 51 +++++++++++++++++-- backend/app/models/wiki_page.rb | 35 +++++++++++-- backend/config/routes.rb | 1 + 5 files changed, 84 insertions(+), 7 deletions(-) diff --git a/backend/Gemfile b/backend/Gemfile index af3b648..73f83db 100644 --- a/backend/Gemfile +++ b/backend/Gemfile @@ -57,3 +57,5 @@ gem "image_processing", "~> 1.14" gem "nokogiri", "~> 1.18" gem 'gollum' + +gem 'diff-lcs' diff --git a/backend/Gemfile.lock b/backend/Gemfile.lock index cd35aa7..aadbea7 100644 --- a/backend/Gemfile.lock +++ b/backend/Gemfile.lock @@ -88,6 +88,7 @@ GEM connection_pool (2.5.3) crass (1.0.6) date (3.4.1) + diff-lcs (1.6.2) dotenv (3.1.8) drb (2.2.1) ed25519 (1.4.0) @@ -412,6 +413,7 @@ PLATFORMS DEPENDENCIES bootsnap brakeman + diff-lcs gollum image_processing (~> 1.14) jwt diff --git a/backend/app/controllers/wiki_pages_controller.rb b/backend/app/controllers/wiki_pages_controller.rb index 2500101..40ba9da 100644 --- a/backend/app/controllers/wiki_pages_controller.rb +++ b/backend/app/controllers/wiki_pages_controller.rb @@ -7,10 +7,51 @@ class WikiPagesController < ApplicationController end def show_by_title - wiki_page = WikiPage.find_by(title: params[:title]) + title = params[:title] + version = params[:version].presence + + wiki_page = WikiPage.find_by(title:) return head :not_found unless wiki_page - render json: wiki_page.as_json.merge(body: wiki_page.body) + wiki_page.sha = version + + body = wiki_page.body + sha = wiki_page.sha + pred = wiki_page.pred + succ = wiki_page.succ + render json: wiki_page.as_json.merge(body:, sha:, pred:, succ:) + end + + def diff + id = params[:id] + from = params[:from] + to = params[:to].presence + return head :bad_request if id.blank? || from.blank? + + wiki_page_from = WikiPage.find(id) + wiki_page_to = wiki_page_from.clone + wiki_page_from.sha = from + wiki_page_to.sha = to + + diffs = Diff::LCS.sdiff(wiki_page_from.body, wiki_page_to.body) + diff_json = diffs.map { |change| + case change.action + when ?= + { type: 'context', content: change.old_element } + when ?| + [{ type: 'removed', content: change.old_element }, + { type: 'added', content: change.new_element }] + when ?+ + { type: 'added', content: change.new_element } + when ?- + { type: 'removed', content: change.old_element } + end }.flatten.compact + + render json: { wiki_page_id: wiki_page_from.id, + title: wiki_page_from.title, + older_sha: wiki_page_from.sha, + newer_sha: wiki_page_to.sha, + diff: diff_json } end def create @@ -57,8 +98,12 @@ class WikiPagesController < ApplicationController render json: log.map { |commit| wiki_page = WikiPage.find(commit.message.split(' ')[1].to_i) + wiki_page.sha = commit.id user = User.find(commit.author.name.to_i) - { sha: commit.id, + { sha: wiki_page.sha, + pred: wiki_page.pred, + succ: wiki_page.succ, + wiki_page: wiki_page && { id: wiki_page.id, title: wiki_page.title }, user: user && { id: user.id, name: user.name }, change_type: commit.message.split(' ')[0].downcase[0...(-1)], diff --git a/backend/app/models/wiki_page.rb b/backend/app/models/wiki_page.rb index 58bbf7e..efe47af 100644 --- a/backend/app/models/wiki_page.rb +++ b/backend/app/models/wiki_page.rb @@ -8,14 +8,41 @@ class WikiPage < ApplicationRecord validates :title, presence: true, length: { maximum: 255 }, uniqueness: true + def sha= val + if val.present? + @sha = val + @page = wiki.page("#{ id }.md", @sha) + else + @page = wiki.page("#{ id }.md") + @sha = @page.versions.first.id + end + vers = @page.versions + idx = vers.find_index { |ver| ver.id == @sha } + @pred = vers[idx + 1]&.id + @succ = idx.positive? ? vers[idx - 1].id : nil + @sha + end + + def sha + @sha + end + + def pred + @pred + end + + def succ + @succ + end + def body - page = wiki.page("#{ id }.md") - page&.raw_data + sha = nil unless @page + @page&.raw_data&.force_encoding('UTF-8') end def set_body content, user: - commit_info = { name: user.id.to_s, - email: 'dummy@example.com' } + commit_info = { name: user.id.to_s, + email: 'dummy@example.com' } page = wiki.page("#{ id }.md") if page commit_info[:message] = "Updated #{ id }" diff --git a/backend/config/routes.rb b/backend/config/routes.rb index ded41c3..a153130 100644 --- a/backend/config/routes.rb +++ b/backend/config/routes.rb @@ -7,6 +7,7 @@ Rails.application.routes.draw do get 'wiki/title/:title', to: 'wiki_pages#show_by_title' get 'wiki/search', to: 'wiki_pages#search' get 'wiki/changes', to: 'wiki_pages#changes' + get 'wiki/:id/diff', to: 'wiki_pages#diff' get 'wiki/:id', to: 'wiki_pages#show' post 'wiki', to: 'wiki_pages#create' put 'wiki/:id', to: 'wiki_pages#update'