코드 블록 슬래시와 되돌리기 수정
This commit is contained in:
@@ -104,6 +104,16 @@ const liveSlashVisible = computed(() => liveSlashSourceLine.value !== null)
|
||||
const liveSlashSuppressedLineList = computed(() => [...liveSlashSuppressedLines.value])
|
||||
|
||||
const visibleLiveSlashCommands = computed(() => filterSlashCommands(liveSlashQuery.value))
|
||||
/** 되돌리기 히스토리 최대 보관 개수 */
|
||||
const EDITOR_UNDO_LIMIT = 100
|
||||
/** @type {import('vue').Ref<string[]>} 본문 되돌리기 스택 */
|
||||
const editorUndoStack = ref([])
|
||||
/** @type {import('vue').Ref<string[]>} 본문 다시 실행 스택 */
|
||||
const editorRedoStack = ref([])
|
||||
/** 히스토리 복원 중 변경 기록을 막는다. */
|
||||
const isRestoringEditorHistory = ref(false)
|
||||
/** 마지막 히스토리 기록 시각 */
|
||||
let lastEditorHistoryRecordAt = 0
|
||||
const mediaPickerAccept = computed(() => {
|
||||
if (['image', 'gallery', 'active-gallery'].includes(mediaPickerTarget.value)) {
|
||||
return 'image/*'
|
||||
@@ -378,6 +388,97 @@ const findCodeFenceRangeAtLine = (lines, targetLine) => {
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* 지정 줄이 코드 펜스 본문 줄인지 확인한다.
|
||||
* @param {string[]} lines - 마크다운 줄 목록
|
||||
* @param {number} lineIndex - 줄 번호
|
||||
* @returns {boolean}
|
||||
*/
|
||||
const isCodeFenceBodyLine = (lines, lineIndex) => {
|
||||
for (let index = 0; index <= lineIndex; index += 1) {
|
||||
if (!String(lines[index] ?? '').trim().startsWith('```')) {
|
||||
continue
|
||||
}
|
||||
|
||||
const closingLine = findNextFencedClosingLine(lines, index, '```')
|
||||
|
||||
if (lineIndex > index && (closingLine === null || lineIndex < closingLine)) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (closingLine !== null) {
|
||||
index = closingLine
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* 현재 선택 위치에 맞춰 에디터 포커스를 복원한다.
|
||||
* @returns {void}
|
||||
*/
|
||||
const restoreEditorFocusAfterHistory = () => {
|
||||
const focusLine = activeLogicalLineIndex.value
|
||||
|
||||
if (activeMode.value === 'write') {
|
||||
focusTextareaAtLine(focusLine)
|
||||
return
|
||||
}
|
||||
|
||||
nextTick(() => {
|
||||
previewRendererRef.value?.focusEditableAtLine(focusLine, 0, 'auto')
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 에디터 히스토리 항목을 기록한다.
|
||||
* @param {string} previousValue - 변경 전 본문
|
||||
* @returns {void}
|
||||
*/
|
||||
const recordEditorHistory = (previousValue) => {
|
||||
if (isRestoringEditorHistory.value) {
|
||||
return
|
||||
}
|
||||
|
||||
const value = String(previousValue ?? '')
|
||||
const now = Date.now()
|
||||
const shouldGroup = now - lastEditorHistoryRecordAt < 900
|
||||
|
||||
if (!shouldGroup || !editorUndoStack.value.length) {
|
||||
editorUndoStack.value = [...editorUndoStack.value, value].slice(-EDITOR_UNDO_LIMIT)
|
||||
}
|
||||
|
||||
editorRedoStack.value = []
|
||||
lastEditorHistoryRecordAt = now
|
||||
}
|
||||
|
||||
/**
|
||||
* 에디터 본문 히스토리를 복원한다.
|
||||
* @param {'undo'|'redo'} direction - 복원 방향
|
||||
* @returns {void}
|
||||
*/
|
||||
const restoreEditorHistory = (direction) => {
|
||||
const sourceStack = direction === 'undo' ? editorUndoStack : editorRedoStack
|
||||
const targetStack = direction === 'undo' ? editorRedoStack : editorUndoStack
|
||||
const nextValue = sourceStack.value[sourceStack.value.length - 1]
|
||||
|
||||
if (typeof nextValue !== 'string') {
|
||||
return
|
||||
}
|
||||
|
||||
sourceStack.value = sourceStack.value.slice(0, -1)
|
||||
targetStack.value = [...targetStack.value, markdownValue.value ?? ''].slice(-EDITOR_UNDO_LIMIT)
|
||||
isRestoringEditorHistory.value = true
|
||||
markdownValue.value = nextValue
|
||||
lastEditorHistoryRecordAt = 0
|
||||
|
||||
nextTick(() => {
|
||||
isRestoringEditorHistory.value = false
|
||||
restoreEditorFocusAfterHistory()
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 라이브 모드에 실제로 존재하는 편집 줄로 포커스 대상을 보정한다.
|
||||
* @param {number} line - 원본 줄 번호
|
||||
@@ -652,6 +753,12 @@ const syncWriteSlashState = () => {
|
||||
}
|
||||
|
||||
const lines = (markdownValue.value ?? '').split('\n')
|
||||
|
||||
if (isCodeFenceBodyLine(lines, line)) {
|
||||
onLiveSlashEnd({ sourceLine: line })
|
||||
return
|
||||
}
|
||||
|
||||
const parsed = parseSlashInput(lines[line] ?? '')
|
||||
|
||||
if (!parsed) {
|
||||
@@ -816,6 +923,14 @@ watch(() => props.modelValue, () => {
|
||||
refreshCaretLogicalLine()
|
||||
})
|
||||
|
||||
watch(markdownValue, (nextValue, previousValue) => {
|
||||
if (nextValue === previousValue) {
|
||||
return
|
||||
}
|
||||
|
||||
recordEditorHistory(previousValue)
|
||||
})
|
||||
|
||||
watch(activeMode, (mode) => {
|
||||
if (mode === 'write') {
|
||||
nextTick(() => {
|
||||
@@ -1007,6 +1122,22 @@ onMounted(() => {
|
||||
return
|
||||
}
|
||||
|
||||
const hasCommandModifier = event.metaKey || event.ctrlKey
|
||||
const isUndoShortcut = hasCommandModifier
|
||||
&& !event.altKey
|
||||
&& !event.shiftKey
|
||||
&& event.key.toLowerCase() === 'z'
|
||||
const isRedoShortcut = hasCommandModifier
|
||||
&& !event.altKey
|
||||
&& (event.shiftKey && event.key.toLowerCase() === 'z' || event.key.toLowerCase() === 'y')
|
||||
|
||||
if (isUndoShortcut || isRedoShortcut) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
restoreEditorHistory(isUndoShortcut ? 'undo' : 'redo')
|
||||
return
|
||||
}
|
||||
|
||||
if (liveSlashVisible.value) {
|
||||
if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
|
||||
event.preventDefault()
|
||||
@@ -2128,6 +2259,13 @@ const onLiveSlashUpdate = (payload) => {
|
||||
return
|
||||
}
|
||||
|
||||
const lines = (markdownValue.value ?? '').split('\n')
|
||||
|
||||
if (isCodeFenceBodyLine(lines, payload.sourceLine)) {
|
||||
onLiveSlashEnd({ sourceLine: payload.sourceLine })
|
||||
return
|
||||
}
|
||||
|
||||
liveSlashSourceLine.value = payload.sourceLine
|
||||
liveSlashQuery.value = String(payload.query ?? '')
|
||||
nextTick(updateLiveSlashMenuPosition)
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
# 업데이트 요약
|
||||
|
||||
## v1.5.89
|
||||
|
||||
- 코드블럭 안의 `/volume1/...` 같은 경로가 슬래시 명령으로 오인되던 문제를 수정했다.
|
||||
- 글쓰기 에디터에서 `Cmd/Ctrl+Z` 되돌리기와 다시 실행을 지원하도록 보강했다.
|
||||
|
||||
## v1.5.88
|
||||
|
||||
- 라이브 글쓰기에서 마지막 인용문 아래 방향키 입력 시 일반 문단으로 빠져나가지 못하던 문제를 수정했다.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 배포 가이드
|
||||
|
||||
> 로컬 기준 v1.5.88에서 `npm run lint`, `npm run build` 검증을 통과했다. NAS 실제 컨테이너 기동과 도메인/프록시 접속 검증은 운영 배포 단계에서 진행한다.
|
||||
> 로컬 기준 v1.5.89에서 `npm run lint`, `npm run build` 검증을 통과했다. NAS 실제 컨테이너 기동과 도메인/프록시 접속 검증은 운영 배포 단계에서 진행한다.
|
||||
|
||||
## 빌드 유형
|
||||
|
||||
@@ -16,6 +16,12 @@
|
||||
|
||||
## 로컬 개발
|
||||
|
||||
### v1.5.89 참고
|
||||
|
||||
- 추가 DB 마이그레이션은 없다.
|
||||
- 게시물 작성 소스 모드에서 코드 블록 본문에 `/volume1/...` 같은 경로를 입력해도 슬래시 명령 메뉴가 열리지 않는지 확인한다.
|
||||
- 소스·라이브 모드에서 줄 삭제나 블록 변환 후 `Cmd/Ctrl+Z`로 되돌리고 `Cmd/Ctrl+Shift+Z`로 다시 실행되는지 확인한다.
|
||||
|
||||
### v1.5.88 참고
|
||||
|
||||
- 추가 DB 마이그레이션은 없다.
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
| components/admin/AdminMediaVideoThumbnail.vue | 관리자 미디어 목록 비디오 항목의 초반 프레임 캔버스 썸네일 |
|
||||
| components/admin/AdminPostForm.vue | 관리자 글 작성/수정 폼, Ghost형 툴바(왼쪽 상태 텍스트·Publish/Update/Unpublish/Unschedule, 서버 반영 상태 기준 분기), 초안만 서버 디바운스 자동 저장·신규 임시 슬러그·발행·예약·멤버십·비공개 상태 저장, 발행 모달(중앙 배치), 좌우 설정 패널(작은 화면은 오른쪽 고정 오버레이), 오른쪽 `View Post` 링크, 오른쪽 하단 본문 통계(단어·문자·공백·읽기 시간·블록·이미지), 미리보기 emit·미저장 이탈 가드, 대표 이미지 본문 상단 표시 토글, 추천 글 토글, 태그 색상 배지 다중 입력·메인 태그 드롭다운·부분 검색 추천 |
|
||||
| components/admin/AdminPageForm.vue | 관리자 페이지 작성/수정 폼, 게시글 작성과 같은 전체 화면 에디터·상단 저장 툴바·접이식 오른쪽 설정 패널, 페이지 공개 상태 선택, HTML 문서 기본 모드, 빈 본문/`!`+Tab HTML 골격 자동 완성, 항상 보이는 일반 텍스트/HTML 모드 선택, 한글 제목 영문 슬러그 자동 변환, HTML textarea 커서 위치 파일 URL 삽입 |
|
||||
| components/admin/AdminMarkdownEditor.vue | 관리자 글 Markdown-first 에디터, 라이브·소스 모드 `/` 슬래시 명령·미디어 모달(이미지·갤러리·비디오·오디오·파일), 커서 블록 컨텍스트·`block-panel` emit, 라이브 이미지 설정 패널·이미지↔갤러리 드래그 변환(`merge-images-to-gallery`·`insert-image-to-gallery`·`extract-gallery-image`), 소스·라이브 `Cmd+Shift+K` 줄 삭제, 소스·라이브 `Cmd/Ctrl+K` 링크 삽입, 코드·콜아웃·토글 내부 줄 삭제, 라이브 fenced 블록 현재 닫는 줄 기준 교체, 블록 패널 바깥 클릭·지원 블록 밖 커서 이동 시 닫기·미디어 모달 중 유지, 인용 마지막 줄 아래 방향키 외부 문단 포커스 이동, 인용·콜아웃·코드·토글 선언 줄 옵션 수정, IME 조합 중 블록 패널 유지, 소스 모드 wrap 라인 번호 보정·라이브↔소스 위치 복원(코드·콜아웃·토글 선언 줄은 본문 줄로 보정), 라이브 슬래시 명령 후 포커스 복원 지연 |
|
||||
| components/admin/AdminMarkdownEditor.vue | 관리자 글 Markdown-first 에디터, 라이브·소스 모드 `/` 슬래시 명령·미디어 모달(이미지·갤러리·비디오·오디오·파일), 코드 블록 본문 슬래시 명령 비활성화, 커서 블록 컨텍스트·`block-panel` emit, 에디터 본문 `Cmd/Ctrl+Z` 히스토리, 라이브 이미지 설정 패널·이미지↔갤러리 드래그 변환(`merge-images-to-gallery`·`insert-image-to-gallery`·`extract-gallery-image`), 소스·라이브 `Cmd+Shift+K` 줄 삭제, 소스·라이브 `Cmd/Ctrl+K` 링크 삽입, 코드·콜아웃·토글 내부 줄 삭제, 라이브 fenced 블록 현재 닫는 줄 기준 교체, 블록 패널 바깥 클릭·지원 블록 밖 커서 이동 시 닫기·미디어 모달 중 유지, 인용 마지막 줄 아래 방향키 외부 문단 포커스 이동, 인용·콜아웃·코드·토글 선언 줄 옵션 수정, IME 조합 중 블록 패널 유지, 소스 모드 wrap 라인 번호 보정·라이브↔소스 위치 복원(코드·콜아웃·토글 선언 줄은 본문 줄로 보정), 라이브 슬래시 명령 후 포커스 복원 지연 |
|
||||
| components/admin/AdminEditorBlockPanel.vue | 게시물 설정 사이드바 오버레이 블록 설정(이미지·갤러리·임베드·인용 배경색·콜아웃 제목·아이콘·배경색·코드·토글), 갤러리 선택 이미지 강조 |
|
||||
| components/admin/AdminBlockEditor.vue | 관리자 글 블록형 에디터, 이미지/갤러리/콜아웃/토글/임베드 블록, 콜아웃 Emoji on/off·이모지 프리셋·인용과 같은 배경 프리셋 선택(우측 고정 설정 패널), 갤러리 복수 미디어 선택·이미지 수별 열 배치·삽입 위치 표시 드래그 순서 변경, 한글 조합 입력 처리, Shift+Enter 줄바꿈, 코드 블록 단축 변환, AFFiNE 참고 세로 막대형 블록 핸들 선택/삭제/드래그 이동과 삽입선 표시, 하단 빈 입력 블록 유지, 본문 placeholder 표시 |
|
||||
| components/admin/AdminTagForm.vue | 관리자 태그 생성/수정 폼(이름/슬러그/설명/색상만 편집) |
|
||||
|
||||
@@ -653,7 +653,7 @@ components/content/
|
||||
- 라이브 모드 갤러리 이미지를 블록 사이 얇은 삽입선(또는 문서 맨 아래 삽입선)에 드롭하면 해당 위치에 단일 이미지 마크다운 줄을 삽입하고 갤러리에서 제거한다(`extract-gallery-image`). 갤러리에 이미지가 1장만 남으면 갤러리 블록을 단일 이미지 줄로 바꾸고, 0장이면 갤러리 블록을 제거한다.
|
||||
- `ProseImage`는 URL이 비어 있거나 로드에 실패해도 최소 높이 placeholder와 「이미지를 불러올 수 없음」 안내를 표시해 라이브 모드에서 블록 선택·편집이 가능하다.
|
||||
- 인용(`>`) 블록은 첫 인용 줄에 `> [!bg=yellow]` 또는 `> {bg=yellow}` 옵션 줄을 두면 해당 줄은 숨기고 블록 배경을 바꾼다. 지원 배경 프리셋은 콜아웃과 같은 `gray`, `blue`, `green`, `yellow`, `red`, `purple`이며, 옵션이 없으면 회색 기본 인용 스타일을 쓴다.
|
||||
- 관리자 **라이브 모드**(미리보기) 인라인 편집: 문단·빈 줄·제목·인용·목록·코드 블록·콜아웃·토글을 렌더 스타일 그대로 contenteditable로 수정한다. blur·문단 이동(방향키) 시 편집 영역의 `<strong>`·`<em>` 등을 `**`·`*` 마크다운으로 다시 직렬화해 저장한다. **Enter**·**Shift+Enter** 모두 다음 문단(블록) 분리. 문단 안 `/`로 슬래시 명령 메뉴(`/image`+Enter 이미지 삽입 등). **소스(작성) 모드** textarea에서도 동일한 `/` 슬래시 메뉴를 사용하며, 상단 마크다운 툴바는 두지 않는다. 슬래시 기본 제목은 **h2·h3·h4**만 표시하며, 본문 **h1**은 `/h1` 검색 시에만 삽입한다(게시물 **제목 필드**가 페이지의 유일한 h1). `Cmd+Shift+K`는 소스 모드와 라이브 모드에서 현재 줄을 삭제하며, 소스 모드에서 여러 줄이 선택되어 있으면 선택 범위가 걸친 줄을 함께 삭제한다. 코드·콜아웃·토글 블록 내부에서는 커서가 있는 본문 줄을 삭제하고, 남은 본문 줄이 1개뿐이면 fenced 블록 전체를 삭제한다. 콜아웃 옵션은 첫 줄 `:::callout emoji=none bg=blue title="주의사항"`처럼 `emoji`·`bg`(gray|blue|green|yellow|red|purple)·`title`로 지정하며, 라이브 모드에서는 블록에 포커스가 들어오면 오른쪽 설정 패널에서 수정한다. 코드 블록은 ` ```언어`·`nolinenos`(줄 번호 숨김)를 지원한다. 라이브·공개 모두 `ProseCodeBlock`(`#15171a`, `px-4 py-3`, `text-sm leading-6`)으로 동일하게 표시한다. 라이브 모드 호버·포커스 시 Language 입력·줄번호 토글이 보인다. 공개 화면에는 언어 라벨 옆 **복사** 버튼으로 본문을 클립보드에 넣는다. 본문 하단 클릭으로 새 문단을 추가한다.
|
||||
- 관리자 **라이브 모드**(미리보기) 인라인 편집: 문단·빈 줄·제목·인용·목록·코드 블록·콜아웃·토글을 렌더 스타일 그대로 contenteditable로 수정한다. blur·문단 이동(방향키) 시 편집 영역의 `<strong>`·`<em>` 등을 `**`·`*` 마크다운으로 다시 직렬화해 저장한다. **Enter**·**Shift+Enter** 모두 다음 문단(블록) 분리. 문단 안 `/`로 슬래시 명령 메뉴(`/image`+Enter 이미지 삽입 등). **소스(작성) 모드** textarea에서도 동일한 `/` 슬래시 메뉴를 사용하되, 코드 fenced 블록 본문 안에서는 `/`를 일반 텍스트로 둔다. 상단 마크다운 툴바는 두지 않는다. 슬래시 기본 제목은 **h2·h3·h4**만 표시하며, 본문 **h1**은 `/h1` 검색 시에만 삽입한다(게시물 **제목 필드**가 페이지의 유일한 h1). `Cmd+Shift+K`는 소스 모드와 라이브 모드에서 현재 줄을 삭제하며, 소스 모드에서 여러 줄이 선택되어 있으면 선택 범위가 걸친 줄을 함께 삭제한다. 코드·콜아웃·토글 블록 내부에서는 커서가 있는 본문 줄을 삭제하고, 남은 본문 줄이 1개뿐이면 fenced 블록 전체를 삭제한다. `Cmd/Ctrl+Z`는 에디터 본문 변경을 되돌리고, `Cmd/Ctrl+Shift+Z` 또는 `Ctrl+Y`는 다시 실행한다. 콜아웃 옵션은 첫 줄 `:::callout emoji=none bg=blue title="주의사항"`처럼 `emoji`·`bg`(gray|blue|green|yellow|red|purple)·`title`로 지정하며, 라이브 모드에서는 블록에 포커스가 들어오면 오른쪽 설정 패널에서 수정한다. 코드 블록은 ` ```언어`·`nolinenos`(줄 번호 숨김)를 지원한다. 라이브·공개 모두 `ProseCodeBlock`(`#15171a`, `px-4 py-3`, `text-sm leading-6`)으로 동일하게 표시한다. 라이브 모드 호버·포커스 시 Language 입력·줄번호 토글이 보인다. 공개 화면에는 언어 라벨 옆 **복사** 버튼으로 본문을 클립보드에 넣는다. 본문 하단 클릭으로 새 문단을 추가한다.
|
||||
- 라이브 모드 공통 편집기는 한글 IME 조합 확정 Enter를 문단·빈 줄의 분리, 제목·목록의 아래 줄 삽입, 토글 제목의 본문 이동, 인용·콜아웃·코드·토글 본문의 텍스트 줄바꿈에 동일하게 연결한다. IME가 확정 Enter의 `keydown`을 전달하지 않고 `keyup`만 남기는 경우에도 조합 종료 직후 Enter로 보고 같은 동작을 실행한다. Shift+방향키 범위 선택은 `ContentMarkdownRenderer` Selection Bridge가 인접 편집 블록까지 확장한다. 단일 줄 블록의 Shift+위/아래는 커서 위치와 상관없이 현재 열 기준으로 이전·다음 편집 블록까지 확장하고, 멀티라인 편집 영역은 첫 줄·마지막 줄 경계에서 `data-source-line`~`data-source-line-end` 줄 범위로 탐색한다. `Cmd/Ctrl+A` 1회는 현재 블록 전체, 짧은 시간 안 2회는 라이브 본문 전체를 선택한다. 교차 블록·전체 선택 상태에서 **Backspace**·**Delete**·**Cmd/Ctrl+X**는 선택 범위를 마크다운 줄로 변환해 `content-replace`로 본문을 갱신한다. 콜아웃·인용 내부 전체 선택 삭제는 블록을 제거하지 않고 빈 본문 줄을 남긴다. 블록 이동 단축키는 Shift 조합일 때 실행하지 않으며, 선택 제스처가 우선한다. 콜아웃 본문은 하나의 멀티라인 편집 영역으로 유지해 `Shift+방향키` 선택이 내부 여러 줄을 가로지를 수 있게 한다. 라이브 멀티라인 블록은 브라우저 기본 DOM 줄 생성 대신 텍스트 값 치환 방식으로 줄바꿈을 삽입하며, contenteditable 값을 읽을 때 끝 줄바꿈을 보존해 첫 줄 빈 줄과 후행 빈 줄이 소스·라이브 모드 전환 또는 저장 중 유실되지 않게 한다. 인용 마지막 줄에서 아래 방향키를 누르면 외부 빈 문단을 만들고 커서를 해당 문단으로 이동하지만, 콜아웃 아래 방향키는 본문 줄을 새로 만들지 않는다.
|
||||
- 인라인 마크다운은 Obsidian식 `$...$` 첨자 토큰을 지원한다. `$H_2O$`는 `H`+아래첨자 `2`+`O`, `$2^8$`은 `2`+위첨자 `8`, `$_B^AR$`는 아래첨자 `B`와 위첨자 `AR`로 렌더링한다. 첨자 본문에 공백·기호가 필요하면 `$_{...}$`, `$^{...}$` 형식도 허용한다.
|
||||
- 라이브 모드 `:::` fenced 블록의 원본 범위는 여는 줄부터 닫는 `:::` 줄까지만 포함한다. 연속된 콜아웃·토글·갤러리 등은 앞 블록 편집 시 다음 블록의 선언 줄을 교체 범위에 포함하지 않는다.
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
# 업데이트 이력
|
||||
|
||||
## v1.5.89
|
||||
|
||||
- 게시물 글쓰기: 소스 모드 코드 블록 본문에서 `/`로 시작하는 경로가 슬래시 명령 메뉴로 오인되지 않도록 수정.
|
||||
- 게시물 글쓰기: 에디터 본문 변경 히스토리를 추가해 `Cmd/Ctrl+Z` 되돌리기와 `Cmd/Ctrl+Shift+Z`/`Ctrl+Y` 다시 실행을 지원.
|
||||
|
||||
## v1.5.88
|
||||
|
||||
- 게시물 글쓰기: 라이브 모드 인용 마지막 줄에서 아래 방향키로 외부 일반 문단을 만들고 커서를 이동하도록 수정.
|
||||
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "sori.studio",
|
||||
"version": "1.5.88",
|
||||
"version": "1.5.89",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "sori.studio",
|
||||
"version": "1.5.88",
|
||||
"version": "1.5.89",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@nuxtjs/tailwindcss": "^6.14.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "sori.studio",
|
||||
"version": "1.5.88",
|
||||
"version": "1.5.89",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"imports": {
|
||||
|
||||
Reference in New Issue
Block a user