diff --git a/backend/app/controllers/wiki_pages_controller.rb b/backend/app/controllers/wiki_pages_controller.rb
index e19557d..9e264fb 100644
--- a/backend/app/controllers/wiki_pages_controller.rb
+++ b/backend/app/controllers/wiki_pages_controller.rb
@@ -126,7 +126,7 @@ class WikiPagesController < ApplicationController
message:,
base_revision_id:)
- render json: WikiPageRepr.base(page).merge(body:), status: :created
+ render json: WikiPageRepr.base(page).merge(body:)
end
def search
diff --git a/frontend/src/components/WikiBody.tsx b/frontend/src/components/WikiBody.tsx
index 50316b2..86381e5 100644
--- a/frontend/src/components/WikiBody.tsx
+++ b/frontend/src/components/WikiBody.tsx
@@ -4,6 +4,7 @@ import ReactMarkdown from 'react-markdown'
import remarkGFM from 'remark-gfm'
import PrefetchLink from '@/components/PrefetchLink'
+import WikiMarkdown from '@/components/WikiMarkdown'
import SectionTitle from '@/components/common/SectionTitle'
import SubsectionTitle from '@/components/common/SubsectionTitle'
import { wikiKeys } from '@/lib/queryKeys'
@@ -16,33 +17,6 @@ import type { Components } from 'react-markdown'
type Props = { title: string
body?: string }
-const mdComponents = { h1: ({ children }) => {children},
- h2: ({ children }) => {children},
- ol: ({ children }) =>
{children}
,
- ul: ({ children }) => ,
- a: (({ href, children }) => (
- ['/', '.'].some (e => href?.startsWith (e))
- ? {children}
- : (
-
- {children}
- ))) } as const satisfies Components
-
-export default (({ title, body }: Props) => {
- const { data } = useQuery ({
- enabled: Boolean (body),
- queryKey: wikiKeys.index ({ }),
- queryFn: () => fetchWikiPages ({ }) })
- const pageNames = (data ?? []).map (page => page.title).sort ((a, b) => b.length - a.length)
-
- const remarkPlugins = useMemo (
- () => [() => remarkWikiAutoLink (pageNames), remarkGFM], [pageNames])
-
- return (
-
- {body || `このページは存在しません。[新規作成してください](/wiki/new?title=${ encodeURIComponent (title) })。`}
- )
-}) satisfies FC
+export default (({ title, body }: Props) =>
+ ) satisfies FC
diff --git a/frontend/src/components/WikiEditForm.tsx b/frontend/src/components/WikiEditForm.tsx
index 14cd4da..be64469 100644
--- a/frontend/src/components/WikiEditForm.tsx
+++ b/frontend/src/components/WikiEditForm.tsx
@@ -12,10 +12,12 @@ type Props = {
title: string
body: string
onSubmit: (title: string, body: string) => void
- forEdit?: boolean }
+ id?: number | null }
-export default (({ title: initTitle, body: initBody, onSubmit, forEdit }: Props) => {
+export default (({ title: initTitle, body: initBody, onSubmit, id }: Props) => {
+ const forEdit = id != null
+
const [title, setTitle] = useState (initTitle)
const [body, setBody] = useState (initBody)
@@ -24,6 +26,21 @@ export default (({ title: initTitle, body: initBody, onSubmit, forEdit }: Props)
setBody (initBody)
}, [initTitle, initBody])
+ const handleImageUpload = async (file: File) => {
+ if (!(forEdit))
+ throw new Error ('画像は Wiki 作成前に追加することができません.')
+
+ const formData = new FormData
+ formData.append ('file', file)
+
+ const asset = await apiPost (
+ `/wiki/${ id }/assets`,
+ formData,
+ { headers: { 'Content-Type': 'multipart/form-data' } })
+
+ return `{{img:${ asset.no }}}`
+ }
+
return (
<>
{/* タイトル */}
@@ -44,7 +61,8 @@ export default (({ title: initTitle, body: initBody, onSubmit, forEdit }: Props)
value={body}
style={{ height: '500px' }}
renderHTML={text => mdParser.render (text)}
- onChange={({ text }) => setBody (text)}/>
+ onChange={({ text }) => setBody (text)}
+ onImageUpload={handleImageUpload}/>
{/* 送信 */}
diff --git a/frontend/src/components/WikiMarkdown.tsx b/frontend/src/components/WikiMarkdown.tsx
new file mode 100644
index 0000000..edb23e2
--- /dev/null
+++ b/frontend/src/components/WikiMarkdown.tsx
@@ -0,0 +1,77 @@
+import { useQuery } from '@tanstack/react-query'
+import { useMemo } from 'react'
+import ReactMarkdown from 'react-markdown'
+import remarkGFM from 'remark-gfm'
+
+import PrefetchLink from '@/components/PrefetchLink'
+import SectionTitle from '@/components/common/SectionTitle'
+import SubsectionTitle from '@/components/common/SubsectionTitle'
+import { wikiKeys } from '@/lib/queryKeys'
+import remarkWikiAutoLink from '@/lib/remark-wiki-autolink'
+import { fetchWikiPages } from '@/lib/wiki'
+
+import type { FC } from 'react'
+import type { Components } from 'react-markdown'
+
+type Props = {
+ title?: string
+ body: string
+ preview?: boolean }
+
+
+const makeComponents = (preview = false) => (
+ { h1: ({ children }) => {children},
+ h2: ({ children }) => {children},
+ ol: ({ children }) => {children}
,
+ ul: ({ children }) => ,
+ a: ({ href, children }) => {
+ if (!(href))
+ return <>{children}>
+
+ if (!(preview) && ['/', '.'].some (e => href.startsWith (e)))
+ return {children}
+
+ const ext = /^(?:https?:)?\/\//.test (href)
+
+ return (
+
+ {children}
+ )
+ },
+ img: (({ src, alt }) => (
+
)),
+ } as const satisfies Components)
+
+
+export default (({ title, body, preview = false }: Props) => {
+ const { data } = useQuery ({
+ queryKey: wikiKeys.index ({ }),
+ queryFn: () => fetchWikiPages ({ }) })
+
+ const pageNames = useMemo (
+ () => (data ?? []).map ((page) => page.title).sort ((a, b) => b.length - a.length),
+ [data])
+
+ const remarkPlugins = useMemo (
+ () => [() => remarkWikiAutoLink (pageNames), remarkGFM],
+ [pageNames])
+
+ const components = useMemo (
+ () => makeComponents (preview),
+ [preview])
+
+ return (
+
+ {body
+ || (title
+ ? ('このページは存在しません。'
+ +`[新規作成してください](/wiki/new?title=${ encodeURIComponent (title) })。`)
+ : '')}
+ )
+}) satisfies FC
diff --git a/frontend/src/pages/wiki/WikiEditPage.tsx b/frontend/src/pages/wiki/WikiEditPage.tsx
index cef9c4a..75c9742 100644
--- a/frontend/src/pages/wiki/WikiEditPage.tsx
+++ b/frontend/src/pages/wiki/WikiEditPage.tsx
@@ -43,8 +43,6 @@ export default (({ user }: Props) => {
{
await apiPut (`/wiki/${ id }`, formData,
{ headers: { 'Content-Type': 'multipart/form-data' } })
- qc.setQueryData (wikiKeys.show (title, { }),
- (prev: WikiPage) => ({ ...prev, title, body }))
qc.invalidateQueries ({ queryKey: wikiKeys.root })
toast ({ title: '投稿成功!' })
navigate (`/wiki/${ title }`)
@@ -78,7 +76,7 @@ export default (({ user }: Props) => {
title={title}
body={body}
onSubmit={handleSubmit}
- forEdit/>)}
+ id={Number (id)}/>)}
)
}) satisfies FC
diff --git a/frontend/src/pages/wiki/WikiNewPage.tsx b/frontend/src/pages/wiki/WikiNewPage.tsx
index 307b1a1..38355ca 100644
--- a/frontend/src/pages/wiki/WikiNewPage.tsx
+++ b/frontend/src/pages/wiki/WikiNewPage.tsx
@@ -38,8 +38,6 @@ export default ({ user }: Props) => {
{
const data = await apiPost ('/wiki', formData,
{ headers: { 'Content-Type': 'multipart/form-data' } })
- qc.setQueryData (wikiKeys.show (data.title, { }),
- (prev: WikiPage) => ({ ...prev, title: data.title, body: data.body }))
qc.invalidateQueries ({ queryKey: wikiKeys.root })
toast ({ title: '投稿成功!' })
navigate (`/wiki/${ data.title }`)