에디터 미디어 적용 버튼 상태 분리
This commit is contained in:
@@ -22,6 +22,7 @@ import {
|
||||
getEditorHistoryEntryValue
|
||||
} from '../../lib/markdown-editor-history.js'
|
||||
import {
|
||||
buildMediaPickerApplyState,
|
||||
buildMediaPickerEmptyMessage,
|
||||
buildMediaPickerUploadHint,
|
||||
buildMediaPickerPageItems,
|
||||
@@ -3373,6 +3374,16 @@ const mediaPickerUploadHint = computed(() => buildMediaPickerUploadHint(
|
||||
*/
|
||||
const mediaPickerEmptyMessage = computed(() => buildMediaPickerEmptyMessage(mediaSearchQuery.value))
|
||||
|
||||
/**
|
||||
* 미디어 선택 적용 버튼 상태를 반환한다.
|
||||
* @returns {{ disabled: boolean, label: string }} 적용 버튼 상태
|
||||
*/
|
||||
const mediaPickerApplyState = computed(() => buildMediaPickerApplyState({
|
||||
selectedUrls: selectedMediaUrls.value,
|
||||
isUploading: isUploading.value,
|
||||
isGallery: isGalleryMediaPicker.value
|
||||
}))
|
||||
|
||||
/**
|
||||
* 붙여넣은 이미지 파일을 업로드한다.
|
||||
* @param {ClipboardEvent} event - 붙여넣기 이벤트
|
||||
@@ -3807,10 +3818,10 @@ const handleKeydown = (event) => {
|
||||
<button
|
||||
class="admin-markdown-editor__media-apply rounded bg-[#15171a] px-4 py-2 text-sm font-semibold text-white disabled:cursor-not-allowed disabled:opacity-40"
|
||||
type="button"
|
||||
:disabled="isUploading || selectedMediaUrls.length === 0"
|
||||
:disabled="mediaPickerApplyState.disabled"
|
||||
@click="applyMediaSelection"
|
||||
>
|
||||
삽입
|
||||
{{ mediaPickerApplyState.label }}
|
||||
</button>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
| lib/navigation-editor-tree.js | 관리자 메뉴 UI·서버 `renumberSortOrderByTree`가 쓰는 `buildNavigationEditorTree`, 관리자 상단 네비 평면 표용 `flattenNavigationEditorWrappers` |
|
||||
| lib/markdown-content-normalizer.js | 관리자 Markdown-first 전환 후 레거시 블록 배열·객체 본문 값을 저장용 마크다운 문자열로 변환 |
|
||||
| lib/markdown-editor-history.js | 관리자 Markdown-first 에디터 undo/redo 히스토리 항목 생성, 레거시 문자열 항목 본문 추출, 선택 범위 보정 |
|
||||
| lib/markdown-editor-media.js | 관리자 Markdown-first 에디터 미디어 선택 모달의 미디어 종류 판별, 대상별 선택 가능 여부, 미리보기 URL, 업로드 MIME 허용, 선택 대상별 제목·accept·API kind·업로드 안내, 라이브러리 빈 상태 문구, 선택 순서·토글·항목 해석, 업로드 오류·한도 검증, 페이지 상태·범위·페이지 번호 계산, fenced 미디어 블록 생성 |
|
||||
| lib/markdown-editor-media.js | 관리자 Markdown-first 에디터 미디어 선택 모달의 미디어 종류 판별, 대상별 선택 가능 여부, 미리보기 URL, 업로드 MIME 허용, 선택 대상별 제목·accept·API kind·업로드 안내, 라이브러리 빈 상태 문구, 적용 버튼 상태, 선택 순서·토글·항목 해석, 업로드 오류·한도 검증, 페이지 상태·범위·페이지 번호 계산, fenced 미디어 블록 생성 |
|
||||
| lib/markdown-block-parser.js | 공개 Markdown 본문 문자열을 제목·문단·이미지·갤러리·fenced 블록·인용·목록·코드·표 렌더링 블록으로 변환 |
|
||||
| lib/markdown-block-context.js | 관리자 Markdown textarea·라이브 편집 포커스 위치 기준 이미지·갤러리·링크·iframe·HTML·인용·콜아웃·코드·토글 블록 설정 패널 대상 판별, 인용 옵션 공통 파서 연결, 코드 fenced 블록 여닫는 펜스 쌍 판별 |
|
||||
| lib/markdown-iframe-embed.js | 게시물 본문 iframe 블록의 코드 판별과 안전 속성 추출, `allowfullscreen`을 `allow=fullscreen` 권한으로 정규화 |
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
# 업데이트 이력
|
||||
|
||||
## v1.11.77
|
||||
|
||||
- 관리자 Markdown 에디터 미디어 선택 적용 버튼 상태 계산을 공통 helper로 분리.
|
||||
- 미디어 선택 적용 버튼 상태 단위 테스트 추가.
|
||||
|
||||
## v1.11.76
|
||||
|
||||
- 관리자 Markdown 에디터 미디어 선택 라이브러리의 빈 상태 문구 계산을 공통 helper로 분리.
|
||||
|
||||
@@ -241,6 +241,27 @@ export const buildMediaPickerEmptyMessage = (searchQuery) => {
|
||||
return '선택할 미디어가 없습니다. 업로드 탭에서 파일을 추가할 수 있습니다.'
|
||||
}
|
||||
|
||||
/**
|
||||
* 미디어 선택 적용 버튼 상태를 만든다.
|
||||
* @param {Object} options - 적용 버튼 상태 옵션
|
||||
* @param {string[]} options.selectedUrls - 선택된 URL 목록
|
||||
* @param {boolean} options.isUploading - 업로드 중 여부
|
||||
* @param {boolean} options.isGallery - 갤러리 다중 선택 여부
|
||||
* @returns {{ disabled: boolean, label: string }} 적용 버튼 상태
|
||||
*/
|
||||
export const buildMediaPickerApplyState = ({
|
||||
selectedUrls,
|
||||
isUploading,
|
||||
isGallery
|
||||
}) => {
|
||||
const selectedCount = Array.isArray(selectedUrls) ? selectedUrls.length : 0
|
||||
|
||||
return {
|
||||
disabled: Boolean(isUploading) || selectedCount <= 0,
|
||||
label: isGallery && selectedCount > 0 ? `${selectedCount}개 삽입` : '삽입'
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 미디어 항목으로 Prose 미디어 블록을 만든다.
|
||||
* @param {'video'|'audio'|'file'} blockType - 블록 유형
|
||||
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "sori.studio",
|
||||
"version": "1.11.76",
|
||||
"version": "1.11.77",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "sori.studio",
|
||||
"version": "1.11.76",
|
||||
"version": "1.11.77",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@nuxtjs/tailwindcss": "^6.14.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "sori.studio",
|
||||
"version": "1.11.76",
|
||||
"version": "1.11.77",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"imports": {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import test from 'node:test'
|
||||
import {
|
||||
buildMediaPickerApplyState,
|
||||
buildMediaPickerEmptyMessage,
|
||||
buildMediaPickerPageItems,
|
||||
buildMediaPickerRangeLabel,
|
||||
@@ -113,6 +114,35 @@ test('미디어 선택 라이브러리 빈 상태 문구를 계산한다', () =>
|
||||
assert.equal(buildMediaPickerEmptyMessage(' car '), '「car」에 맞는 미디어가 없습니다.')
|
||||
})
|
||||
|
||||
test('미디어 선택 적용 버튼 상태를 계산한다', () => {
|
||||
assert.deepEqual(buildMediaPickerApplyState({
|
||||
selectedUrls: [],
|
||||
isUploading: false,
|
||||
isGallery: false
|
||||
}), {
|
||||
disabled: true,
|
||||
label: '삽입'
|
||||
})
|
||||
|
||||
assert.deepEqual(buildMediaPickerApplyState({
|
||||
selectedUrls: ['/a.png'],
|
||||
isUploading: true,
|
||||
isGallery: false
|
||||
}), {
|
||||
disabled: true,
|
||||
label: '삽입'
|
||||
})
|
||||
|
||||
assert.deepEqual(buildMediaPickerApplyState({
|
||||
selectedUrls: ['/a.png', '/b.png'],
|
||||
isUploading: false,
|
||||
isGallery: true
|
||||
}), {
|
||||
disabled: false,
|
||||
label: '2개 삽입'
|
||||
})
|
||||
})
|
||||
|
||||
test('미디어 항목으로 fenced 미디어 블록을 만든다', () => {
|
||||
assert.deepEqual(createMediaBlockMarkdown('video', {
|
||||
url: '/uploads/a.mp4',
|
||||
|
||||
Reference in New Issue
Block a user