This translation is older than the English page and may be missing recent changes.
Read the English version텍스트 영역을 대체하는 대신 텍스트 영역을 향상시키는 감점 편집기이므로 양식 제출, 유효성 검사 및 필수 필드가 계속 작동합니다. 위지윅 및 일반 마크다운 모드, 실시간 미리보기, 찾기 및 바꾸기, RTL 지원, 다크 모드. Django, Laravel, Rails, Node.js, PHP 및 모든 스택에서 독립 실행형으로 작동합니다.
-
- Frutjam과 Tailwind가 필요하지 않습니다. * * 스타일이 번들로 제공되므로 편집기는 모든 프로젝트에 참여할 수 있습니다.
설치
NPM (번들러: 바이트, 웹팩, 롤업 등)
npm install markdown-text-editor |
1 2 | import MarkdownEditor from 'markdown-text-editor'; new MarkdownEditor('#markdown-editor'); |
TypeScript 정의는 패키지와 함께 제공되므로 옵션, 도구 모음 항목 및 변수 모양이 추가 설치 없이 검사되고 자동 완성됩니다.
유형도 가져올 수 있으므로 통화 사이트에 옵션이 인라인으로 작성되지 않을 때마다 중요합니다. TypeScript는 직접 전달된 개체 리터럴에서 알 수 없는 키만 검사하므로 자체 변수에 보관된 구성에는 맞춤법이 틀린 키가 자동으로 무시됩니다. 주석을 달면 수표가 되돌아갑니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 | import MarkdownEditor, { type MarkdownEditorOptions, type ToolbarEntry } from 'markdown-text-editor'; // Without the annotation this compiles, the editor renders with the default // toolbar, and nothing tells you why. const config: MarkdownEditorOptions = { placeholder: 'Write...', toolbr: ['bold', 'preview'], // Error: did you mean to write 'toolbar'? }; // Building a toolbar conditionally const toolbar: ToolbarEntry[] = ['bold', 'italic']; if (canUpload) toolbar.push({ image: { fileInput: { uploadUrl: '/api/upload' } } }); toolbar.push('preview'); |
래퍼 컴포넌트도 마찬가지입니다. MarkdownEditorOptions 대신 전달하는 것입니다. any그래서 당신의 래퍼를 사용하는 사람은 검사를 유지합니다.
1 2 3 4 | interface EditorProps { value: string; options?: MarkdownEditorOptions; } |
CDN: ES 모듈
1 2 3 4 | <script type="module"> import MarkdownEditor from 'https://cdn.jsdelivr.net/npm/markdown-text-editor/+esm'; new MarkdownEditor('#markdown-editor'); </script> |
CDN: 글로벌 스크립트 태그 (IIFE)
가져오기 필요 없음: MarkdownEditor는 자동으로 전역 변수로 사용할 수 있습니다.
1 2 3 4 5 6 7 8 9 | <form action="/api/save" method="POST"> <textarea id="markdown-editor" name="content"># Hello World</textarea> <button type="submit">Save Content</button> </form> <script src="https://cdn.jsdelivr.net/npm/markdown-text-editor"></script> <script> new MarkdownEditor('#markdown-editor'); </script> |
마크다운 에디터
빠른 설치
옵션 객체를 전달하여 편집기를 사용자 정의합니다. 모든 옵션은 선택 사항입니다. 기본값을 사용하려면 아무 것도 생략하십시오.
1 2 3 4 | const editor = new MarkdownEditor('#markdown-editor', { placeholder: 'Write your markdown...', toolbar: ['heading', 'bold', 'italic', 'strikethrough', 'ul', 'ol', 'checklist', 'blockquote', 'link', 'preview'], }); |
철학: "Native-First"
대부분의 편집자는 표준 웹 워크플로우를 위반합니다. * * MarkdownEditor * * 는 그것을 수용합니다. 왜냐하면 그것은 <textarea>데이터를 처리하는 새로운 방법을 배울 필요가 없습니다.
-
-
- 데이터 바인딩 필요 없음: * * 와 호환
<form method="POST">수백 대 지원 가능
- 데이터 바인딩 필요 없음: * * 와 호환
-
-
-
- 표준 액세스: * * 사용
document.getElementById('editor').value일반 입력처럼 말이죠.
- 표준 액세스: * * 사용
-
-
-
- 백엔드 불가지론: * * 일반 양식 필드와 마찬가지로 모든 백엔드 (Python, Node.js, PHP 등) 에서 작동합니다.
-
MarkdownEditor vs EasyMDE/SimpleMDE
대부분의 JavaScript 마크다운 편집기 (EasyMDE, SimpleMDE, CodeMirror 기반 편집기) * * <textarea>* * 양식이 제출되면 내용을 다시 작성하여 사본을 편집합니다. 다른 값이 필요할 때까지 작동합니다: a required 브라우저가 초점을 맞출 수 없는 필드는 제출물을 완전히 차단합니다. .value 또는 FormData read before submit은 htmx, Turbo, autosave 및 unsaved-changes 가드를 파괴하는 빈 문자열을 반환합니다. * * MarkdownEditor는 다릅니다. * * 이미 있는 텍스트 영역의 스타일을 지정하고 입력한 필드로 남겨두므로 매 순간 값이 정확합니다.
| 추천 | MarkdownEditor | EasyMDE/SimpleMDE |
|---|---|---|
| 보존된 네이티브 텍스트 영역 | ✅ | ❌ 숨김, 사본으로 편집됨 |
다음과 함께 작동합니다. required -항목 | ✅ | ❌ 브라우저가 제출을 차단합니다 |
.value 제출하기 전에 수정 | ✅ | 양식이 제출될 때까지 ❌ 비어 있음 |
로 직렬화 FormData, htmx, 터보 | ✅ | 에디터 자체 API ❌ 필요 |
| 위지윅 하이브리드 모드 | ✅ | ❌ |
| 내장된 찾기 및 바꾸기 | ✅ | ❌ |
| RTL 지원 | 내장 | CodeMirror를 통해 direction 옵션 |
| 인라인 이벤트 처리기 (CSP) | 없음 | 어느 정도 줌 |
| 다크 모드/테마 | ✅ | 한정 |
| 번들 크기 (gz 압축) | 53 KB | 107KB (JS + CSS) |
프레임워크 통합
-
- MarkdownEditor * * 는 네이티브를 유지하기 때문에
<textarea>추가 코드 없이 모든 백엔드 프레임워크와 통합됩니다. 서버는 표준 양식 필드에서와 동일한 감점 내용을 받습니다. React와 Vue의 경우 이 섹션의 끝 부분에서 다루는 몇 줄이 필요합니다.
- MarkdownEditor * * 는 네이티브를 유지하기 때문에
장고
추가 class 텍스트 영역 위젯으로 이동하여 편집기를 초기화합니다. request.POST['content'] 추가 단계 없이 작동합니다.
1 2 3 4 5 6 7 8 | # forms.py class PostForm(forms.ModelForm): class Meta: model = Post fields = ['content'] widgets = { 'content': forms.Textarea(attrs={'class': 'markdown-editor'}), } |
1 2 | new MarkdownEditor('.markdown-editor'); // request.POST['content'] contains the markdown on submit |
라라벨
사용 f.text_area 클래스와 함께: $request->input('content') 감점을 직접 받습니다.
1 2 | <textarea name="content" class="markdown-editor">{{ old('content') }}</textarea> <script>new MarkdownEditor('.markdown-editor');</script> |
루비 온 레일
다음과 함께 작동합니다. form_with 수백 대 지원 가능 params[:content] 감점이 포함되어 있습니다. 터보 드라이브의 경우 turbo:load 대신에 DOMContentLoaded.
1 2 3 4 5 6 | document.addEventListener('turbo:load', () => { document.querySelectorAll('.markdown-editor:not([data-mde-init])').forEach(el => { el.setAttribute('data-mde-init', 'true'); new MarkdownEditor(el); }); }); |
Node.js/Express
req.body.content 양식 제출 시 감점을 받습니다: 동기화 단계 없음, 사용자 정의 추출 없음.
1 2 3 | <textarea name="content" class="markdown-editor"></textarea> <script src="https://cdn.jsdelivr.net/npm/markdown-text-editor"></script> <script>new MarkdownEditor('.markdown-editor');</script> |
PHP
$_POST['content'] 표준 텍스트 영역과 동일하게 작동합니다. 드롭 인하고 기존 양식 처리를 변경하지 않아도 됩니다.
1 2 3 4 5 6 | <form method="POST" action="save.php"> <textarea name="content" class="markdown-editor"></textarea> <button type="submit">Save</button> </form> <script src="https://cdn.jsdelivr.net/npm/markdown-text-editor"></script> <script>new MarkdownEditor('.markdown-editor');</script> |
반응
효과에서 편집기를 만들고 마운트 해제 시 제거합니다. 사용 defaultValue 전체 인프라를 value: 편집기가 텍스트 영역에 직접 쓰므로 제어된 바인딩이 사용자가 입력하는 내용을 덮어씁니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 | import { useEffect, useRef } from 'react'; import MarkdownEditor from 'markdown-text-editor'; function MarkdownField({ name, defaultValue = '', onChange }) { const ref = useRef(null); useEffect(() => { const editor = new MarkdownEditor(ref.current, { onChange }); return () => editor.destroy(); }, []); return <textarea ref={ref} name={name} defaultValue={defaultValue} />; } |
재방문자 editor.destroy() 이 효과에서 StrictMode도 다룹니다. StrictMode는 개발 중인 효과를 두 번 실행하고 그렇지 않으면 한 텍스트 영역에 두 명의 편집자를 남깁니다. 빈 종속성 배열은 의도적입니다. 옵션은 편집기를 만들 때 한 번 읽으므로 효과를 다시 실행하면 모든 변경 사항에 대해 해당 배열을 해체하고 다시 빌드합니다.
Vue
같은 생각입니다. 에서 초기값을 한 번 설정하십시오. onMounted 바인딩하지 마십시오. :value또는 를 통해 다시 방출되는 모든 키 입력 v-model 텍스트 영역을 덮어씁니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <script setup> import { ref, onMounted, onBeforeUnmount } from 'vue'; import MarkdownEditor from 'markdown-text-editor'; const el = ref(null); const props = defineProps({ modelValue: { type: String, default: '' } }); const emit = defineEmits(['update:modelValue']); let editor = null; onMounted(() => { el.value.value = props.modelValue; editor = new MarkdownEditor(el.value, { onChange: value => emit('update:modelValue', value) }); }); onBeforeUnmount(() => editor?.destroy()); </script> <template><textarea ref="el"></textarea></template> |
'이라는 것은 그냥 ' . <MarkdownField v-model="content" />. 평범한 형태로 건너뛸 수 있습니다. v-model 다른 프레임워크와 마찬가지로 제출 시 텍스트 영역의 값을 완전히 읽습니다.
구성
다음을 전달하여 편집기의 동작과 인터페이스를 완전히 사용자 정의할 수 있습니다. options object. 옵션을 생략하면 * * default * * 값이 사용됩니다.
옵션은 편집기가 구성될 때 한 번 읽힙니다. 이후에 변경해도 아무런 영향이 없습니다: call destroy() 대신 새 편집기를 만듭니다.
| 속성 | 유형 | 기본 | 목적 |
|---|---|---|---|
mode | string | 'plain' | 초기 보기를 설정합니다. WYSIWYG 경험을 위해 하이브리드를 사용하거나 원시 구문을 위해 일반을 사용하십시오. |
placeholder | string | 'Write...' | 편집기가 비어 있을 때 표시되는 텍스트입니다. |
toolbar | array | [...] | 어떤 도구가 표시되고 어떤 순서로 표시되는지 정의합니다. |
footer | 거짓 | 대상 | 모두 |
theme | string | inherited | 편집기 테마 (라이트, 다크, 스노우베리, 다크베리) 를 명시적으로 설정합니다. 생략하면 편집기는 data-theme 가장 가까운 조상 요소 또는 <textarea> 현재 동영상 |
minHeight | number | 200 | 콘텐츠가 짧을 때 편집기가 축소할 최소 높이 (픽셀) 입니다. maxHeight 자동 성장 범위를 설정합니다. |
maxHeight | number | 500 | 전체 화면이 아닌 모드에서 편집기가 확장할 수 있는 최대 높이 (픽셀) 입니다. 콘텐츠가 이 높이를 초과하면 편집기 내부에 스크롤 막대가 나타납니다. 편집기에는 드래그 핸들도 있어 사용자가 이 제한을 초과하여 수동으로 크기를 조정할 수 있습니다. |
renderer | function | marked | 미리 보기에 사용된 감점 분석기를 대체합니다. 마크다운 문자열을 수신하고 HTML 문자열을 반환해야 합니다. |
sanitizer | function | DOMPurify | HTML 살균제를 교체합니다. 렌더링된 HTML을 수신하고 표시할 안전한 HTML을 반환해야 합니다. |
onChange | function | undefined | 입력, 도구 모음 작업, 실행 취소/다시 실행, 목록 연속 등 콘텐츠가 변경될 때마다 콜백이 실행됩니다. 현재 마크다운 문자열을 유일한 인수로 받습니다. |
labels | object | undefined | 영어 문자열로 입력된 편집자 자체 인터페이스에 대한 번역입니다. 생략한 내용은 모두 영어로 유지됩니다. |
🛠 도구 모음 사용자 정의
도구 모음은 모듈식입니다. 어레이를 수정하여 최소한의 경험이나 모든 기능을 갖춘 전원 제품군을 만들 수 있습니다.
사용 가능한 도구
| 범주 | 도구 키 |
|---|---|
| 타이포그래피 | heading, bold, italic, strikethrough, blockquote |
| 기울기 | ul (bullet), ol (numbered), checklist |
| 암호 | code (인라인), codeblock (울타리 블록) |
| 인서트 | hr (수평 법칙), table (테이블 템플릿) |
| 메디아 | link, image |
| 편집 | undo, redo, indent, outdent |
| 보다 | preview |
| 템플릿 | { variables: [...] }, 인라인으로 구성됨 |
도구 참조
| 도구 | 설명 |
|---|---|
heading | 제목 수준 H1~H6을 선택하는 드롭다운을 엽니다. |
bold | 굵은 텍스트 형식을 활성화합니다. |
italic | 기울임꼴 텍스트 서식을 활성화합니다. |
strikethrough | 텍스트 취소선을 허용합니다. |
ol | (순서가 지정된 목록): 텍스트를 번호가 매겨진 목록 형식으로 변환합니다. |
ul | (순서가 없는 목록): 텍스트를 글머리 기호 목록으로 변환합니다. |
checklist | 텍스트에 확인란을 추가하여 작업, 할 일 목록 또는 완료 상태 추적에 적합합니다. |
blockquote | 인용되거나 강조된 텍스트를 강조표시합니다. |
code | 인라인 코드에 대해 단일 백틱으로 선택한 텍스트를 래핑합니다. 다시 클릭하면 백틱이 제거됩니다. |
codeblock | 삼중 백틱 울타리 코드 블록에서 선택한 텍스트를 래핑합니다. 다시 클릭하면 울타리가 제거됩니다. |
hr | 삽입 --- 자체 줄의 커서 위치에 수평선을 놓습니다. |
table | 커서 위치에 스타터 2x3 마크다운 테이블 템플릿을 삽입합니다. |
image | 마크다운 구문을 통해 이미지를 삽입할 수 있습니다. |
link | 텍스트에 하이퍼링크를 추가할 수 있습니다. |
undo | 마지막 변경 사항을 되돌리려면 |
redo | 마지막으로 실행 취소된 변경 사항을 다시 적용합니다. |
indent | 들여쓰기 수준을 높이려면 |
outdent | 들여쓰기 수준을 줄입니다. |
preview | 전체 화면 병렬 미리보기를 전환합니다. 미리보기 창의 확인란을 클릭할 수 있으며 마크다운 소스를 즉시 업데이트할 수 있습니다. 전체 화면을 종료하려면 Esc를 누르세요. 고정 헤더가 전체 화면에서 편집기를 덮는 경우 다음을 참조하세요. --mte-fullscreen-z-index. |
💡 구현 팁:
- 재순서: 버튼은 배열에 나열한 정확한 순서대로 나타납니다.
- 제거: 아무 키나 생략하면 됩니다(예:
image) 어레이에서 사용자에 대해 해당 기능을 완전히 비활성화합니다. - 기본 대체:
placeholderJS에서는 플러그인이 자동으로placeholderHTML의 속성<textarea>
🧩 사용자 정의 도구
포크하지 않고 나만의 도구 모음 버튼을 추가하세요. 설명하고 에 넣습니다. toolbar 원하는 위치에 배열하세요.
1 2 3 4 5 6 7 8 9 10 11 | new MarkdownEditor('#markdown-editor', { toolbar: ['bold', 'italic', { custom: { title: 'Callout', icon: '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20">…</svg>', action(editor) { editor.insertText('> [!NOTE]\n> Something worth noting'); } } }, 'preview'] }); |
그만큼 title 툴팁과 버튼의 CSS 클래스가 되므로 다음과 같이 스타일을 지정할 수 있습니다. .callout-btn, 내장 도구와 똑같습니다.
여러 도구
원하는 만큼 추가하세요. 각각은 배열의 자체 항목이므로 개별적으로 배치하면 한쪽 끝에 그룹화되지 않고 내장 도구 사이에 배치될 수 있습니다.
1 2 3 4 5 6 7 | toolbar: [ 'bold', 'italic', { custom: { title: 'Callout', icon: svg1, action: insertCallout } }, 'ul', 'ol', { custom: { title: 'Signature', icon: svg2, action: insertSignature } }, 'preview' ] |
각자에게 개성을 부여하라 title. 제목을 공유하는 두 도구는 CSS 클래스를 공유하고, 제목이 없는 도구는 CSS 클래스로 대체됩니다. .custom-btn.
옵션
| 속성 | 유형 | 목적 |
|---|---|---|
title | string | 필수의. 도구 설명 텍스트 및 버튼의 CSS 클래스 소스입니다. 다음을 통해 번역 가능 labels. |
action | function | 필수의. 수신 (editor, event). 클릭 이벤트가 전달되므로 대화 상자를 여는 도구가 이를 전달할 수 있습니다. MarkdownEditor.modal. |
icon | string | 버튼 면의 인라인 SVG입니다. |
shortcut | string | 다음과 같은 키보드 단축키 Ctrl+Shift+K. 툴팁에 추가되며 동일한 키를 사용하는 내장 항목보다 우선합니다. |
없는 도구 action 도구 모음이 깨지는 대신 콘솔 경고와 함께 건너뜁니다. 버튼을 렌더링하지 않으며 shortcut, 선언한 경우에도 등록되지 않습니다.
콘텐츠 작업
사용 editor.insertText() 텍스트 영역에 직접 쓰는 것보다. 선택 항목을 바꾸고, 포커스를 복원하고, 캐럿을 이동하고, 스크롤하고, 미리보기를 다시 렌더링하고 실행합니다. onChange. 편집 내용이 일반 경로를 통과하므로 실행 취소가 계속 작동합니다.
1 2 3 4 5 6 7 8 | action(editor) { const textarea = editor.usertextarea; const selected = textarea.value.slice(textarea.selectionStart, textarea.selectionEnd); const wrapped = `==${selected || 'highlight'}==`; // (text, where the caret lands, characters to leave outside the selection) editor.insertText(wrapped, wrapped.length, 0); } |
단축키
1 2 3 4 5 6 | { custom: { title: 'Highlight', icon: '<svg>…</svg>', shortcut: 'Ctrl+Shift+H', action: (editor) => editor.insertText('====', 2, 2) }} |
툴팁은 "강조 표시(Ctrl+Shift+H)"가 됩니다. 도구 단축키는 내장된 단축키보다 먼저 확인되므로 사용자 정의 도구는 의도적으로 편집기에서 처리할 조합을 대신할 수 있습니다.
자체 마크업이 필요한 도구
드롭다운이나 대화 상자는 선언적으로 설명할 수 없으므로 대신 클래스를 작성하세요. 연장하다 MarkdownEditor.Tool, 세트 this.button 생성자에서 구현하고 applySyntax().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | class EmbedTool extends MarkdownEditor.Tool { constructor(editor) { super(editor, 'Embed video'); // tooltip, and .embed-video-btn this.shortcut = 'Ctrl+Shift+E'; // optional this.button = this.createButton('<svg>…</svg>'); } applySyntax(event) { const dialog = MarkdownEditor.modal(event, 'fj:max-w-sm', ` <input type="url" class="embed-url fj:me-input fj:w-full"> <button type="button" class="embed-go fj:me-btn fj:me-btn-sm">Insert</button> `, 'Embed'); dialog.querySelector('.embed-go').addEventListener('click', () => { const url = dialog.querySelector('.embed-url').value.trim(); if (url) this.editor.insertText(`\n<iframe src="${url}"></iframe>\n`); dialog.close(); }); } destroy() { // Called by editor.destroy(). Release anything you registered here. } } new MarkdownEditor('#markdown-editor', { toolbar: ['bold', EmbedTool, 'preview'] }); |
다음을 사용하여 구성 전달 { tool: EmbedTool, config: {...} }, 생성자의 두 번째 인수로 도착합니다. 환경 this.button 에게 null 아무것도 렌더링하지 않습니다. 이는 일부 구성에만 적용되는 도구에 유용합니다.
한 가지 주목할 점: Tool의 생성자 호출 createButton(), 따라서 재정의에 필요한 모든 항목은 다음에서 와야 합니다. this.editor, 이후에 할당한 필드가 아님 super().
대화 도우미
MarkdownEditor.modal 는 내장 링크 및 이미지 도구가 사용하는 대화 상자이므로 입력을 수집하는 도구는 자체 팝업을 만드는 대신 나머지 편집기처럼 보입니다. 그것은 <dialog> 요소, 이미 열려 있으며 필드를 쿼리하고 다음으로 닫습니다. dialog.close().
1 2 | // (event, size classes, body HTML, aria label) const dialog = MarkdownEditor.modal(event, 'fj:max-w-sm', '…', 'Embed'); |
통과 event 당신의 applySyntax() 받았다. 도우미는 클릭이 발생한 편집기를 찾기 위해 이를 읽고 대화 상자가 해당 편집기의 래퍼 내부에 추가되고 해당 테마를 선택합니다. 이는 해당 편집기에 이미 열려 있는 모든 대화 상자를 대체하고 닫히면 DOM에서 자체적으로 제거되므로 정리할 것이 없습니다.
마크다운 직접 렌더링
도구에 렌더링된 콘텐츠(예: 도구 설명 본문)가 포함된 경우 editor.renderMarkdown() 미리보기와 똑같이 HTML을 생성하여 renderer 그리고 sanitizer.
const html = editor.renderMarkdown('**bold** text'); |
자신만의 텍스트 영역을 위한 도구 모음
대화 상자가 서식 있는 텍스트를 수집할 때 다시 작성하는 대신 실제 서식 도구를 제공하세요. 도구 모음은 전달한 텍스트 영역에 바인딩되어 있습니다. labels 상속되며 미리보기 버튼이 추가되지 않습니다.
1 2 3 | const body = dialog.querySelector('textarea'); const bar = editor.createToolbar(body, ['bold', 'italic', 'strikethrough']); dialog.querySelector('.body-toolbar').appendChild(bar); |
도구 모음의 수명은 관리되지 않습니다. 버튼은 제거될 때 대화 상자와 함께 정리되지만, 그 안에 있는 도구가 페이지 전체, 문서 리스너 또는 타이머를 등록하는 경우 대화 상자가 닫힐 때 직접 해제하십시오.
번역
사용자 정의 도구는 사용자가 지정한 제목을 기준으로 내장된 도구처럼 번역됩니다.
labels: { 'Callout': 'Aviso', 'Embed video': 'Insertar video' } |
CSS 클래스는 영향을 받지 않습니다. .callout-btn 숙박 .callout-btn 모든 언어로.
📊 바닥글(상태 표시줄)
바닥글은 편집기 아래에 위치하며 커서의 줄, 열, 문서의 문자 수 및 선택적으로 단어 수를 표시하며 모두 실시간으로 업데이트됩니다. 이는 기본적으로 표시되며 각 통계는 독립적으로 전환될 수 있습니다.
| 열쇠 | 유형 | 기본 | 설명 |
|---|---|---|---|
line | boolean | true | 현재 줄 번호를 표시합니다. |
col | boolean | true | 현재 열 번호를 표시합니다. |
chars | boolean | true | 총 문자 수를 표시합니다. |
words | boolean | false | 총 단어 수를 표시합니다. 기본적으로 꺼짐: 다음으로 설정 true 활성화합니다. |
사용 예
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // Default — line, col, and chars visible new MarkdownEditor('#editor'); // Disable the footer entirely new MarkdownEditor('#editor', { footer: false }); // Hide only character count new MarkdownEditor('#editor', { footer: { chars: false } }); // Hide line and column, keep character count new MarkdownEditor('#editor', { footer: { line: false, col: false } }); // Show only line number new MarkdownEditor('#editor', { footer: { col: false, chars: false } }); // Enable word count alongside the defaults new MarkdownEditor('#editor', { footer: { words: true } }); // Show word count only new MarkdownEditor('#editor', { footer: { line: false, col: false, chars: false, words: true } }); |
🔀 편집 모드
MarkdownEditor는 콘텐츠를 작성하고 형식을 지정하는 두 가지 고유한 방법을 제공합니다. 기존 구문 중심 보기 또는 현대적인 시각적 우선 환경 간에 전환할 수 있습니다.
plain(기본값): 구문(예:**bold**또는# heading)이 보입니다. 개발자와 Markdown 순수주의자에게 이상적hybrid: 기본 Markdown 구조를 유지하면서 입력할 때 서식(굵게, 기울임꼴, 제목)을 실시간으로 렌더링하는 WYSIWYG에서 영감을 받은 경험입니다.
1 2 3 4 5 6 7 8 9 10 11 12 | // Default initialization (Plain Mode) new MarkdownEditor('#markdown-editor'); // Explicit Plain Mode new MarkdownEditor('#markdown-editor', { mode: 'plain' }); // Hybrid (Visual) Mode new MarkdownEditor('#markdown-editor', { mode: 'hybrid' }); |
하이브리드 및 일반 모드 미리보기:
하이브리드 모드
입력하는 동안 시각적 서식이 실시간으로 렌더링됩니다.
일반 모드(기본값)
가벼운 경험을 위해 원시 Markdown 구문에 중점을 둡니다.
🌙 테마
MarkdownEditor는 주변 페이지에서 테마를 자동으로 상속하므로 구성이 필요하지 않습니다. 편집자가 읽어요 data-theme 초기화 시 가장 가까운 상위 항목에서 가져오므로 기본적으로 사이트 테마와 동기화가 유지됩니다.
테마 해결 방법(우선순위)
theme옵션: 옵션 개체에 전달된 명시적 재정의data-theme에<textarea>: 요소에 직접 설정data-theme모든 조상에서: 예:<html>,<body>또는 래퍼<div>
사용 가능한 테마
'light' (기본), 'dark', 'snowberry', 'darkberry'
옵션 1, 다음에서 상속 <html> 또는 모든 조상(구성 없음)
1 2 3 4 5 6 | <html data-theme="dark"> ... <textarea id="markdown-editor"></textarea> <script> new MarkdownEditor('#markdown-editor'); // picks up dark automatically </script> |
옵션 2: 설정 data-theme 에 직접 <textarea>
1 2 3 4 | <textarea id="markdown-editor" data-theme="dark"></textarea> <script> new MarkdownEditor('#markdown-editor'); </script> |
옵션 3: 명시적 theme 옵션(모든 것을 무시함)
1 2 3 | new MarkdownEditor('#markdown-editor', { theme: 'dark' }); |
🎨 CSS 변수를 통한 맞춤 테마
CSS 변수를 재정의하여 편집기의 모양을 완전히 사용자 정의할 수 있습니다. .markdown-editor-wrapper 요소 또는 기타 [data-theme] 선택자. 모든 색상은 다음을 사용합니다. OKLCH 색 공간 지각적으로 균일한 결과를 얻으려면
| 변하기 쉬운 | 목적 | 라이트 기본값 | 어두운 기본값 |
|---|---|---|---|
--color-base | 에디터 배경 | oklch(100% 0 0) | oklch(10.9% 0 0) |
--color-on-base | 기본 텍스트 색상 | oklch(22% 0 0) | oklch(98% 0 0) |
--color-primary | 기본 악센트(도구 모음 활성화, 링크) | oklch(51.1% .262 277) | oklch(66.4% .184 286) |
--color-on-primary | 원색 표면의 텍스트 | oklch(96.2% .018 272) | oklch(10% .01 270) |
--color-secondary | 보조 악센트 | oklch(59.1% .293 323) | oklch(65% .18 220) |
--color-accent | 악센트 강조(인라인 코드, 기울임꼴) | oklch(54.1% .281 293) | oklch(75% .18 50) |
--color-neutral | 중립 표면(테두리, 구분선) | oklch(15% 0 0) | oklch(85% 0 0) |
--color-error | 오류 상태 색상 | oklch(57.7% .245 27) | oklch(60% .22 30) |
--border-radius | 편집기 프레임의 모서리 라운딩 | 0.25rem |
맞춤 테마 예
모든 변수를 재정의합니다. .markdown-editor-wrapper 편집기가 초기화되거나 사용자 정의를 정의한 후 [data-theme] 스타일시트에서 차단하세요.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | /* Override individual variables */ .markdown-editor-wrapper { --color-primary: oklch(60% 0.2 30); /* orange accent */ --border-radius: 0.5rem; } /* Or define a full custom theme */ [data-theme="brand"] .markdown-editor-wrapper, .markdown-editor-wrapper[data-theme="brand"] { --color-base: oklch(15% 0.01 250); --color-on-base: oklch(95% 0 0); --color-primary: oklch(65% 0.22 145); /* green */ --color-on-primary: oklch(10% 0 0); --color-accent: oklch(75% 0.18 60); --color-neutral: oklch(80% 0 0); --border-radius: 0.75rem; } |
new MarkdownEditor('#markdown-editor', { theme: 'brand' }); |
🌐 인터페이스 언어
편집기 자체의 텍스트, 도구 설명, 메뉴 항목, 모달 필드 및 버튼은 기본적으로 영어입니다. 통과 labels 번역할 개체입니다. 키는 gettext가 작동하는 방식인 영어 문자열이므로 변경하려는 항목만 나열하고 누락된 항목은 영어로 대체됩니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 | new MarkdownEditor('#markdown-editor', { labels: { 'Bold': 'Gras', 'Italic': 'Italique', 'Heading': 'Titre', 'Link': 'Lien', 'Image link': 'Lien de l\'image', 'URL': 'URL', 'Alt text': 'Texte alternatif', 'Apply': 'Appliquer', 'Uploading...': 'Téléversement...', }, }); |
이는 오른쪽에서 왼쪽으로 읽는 콘텐츠와 함께 가장 중요합니다. 아랍어, 우르두어 및 페르시아어는 자체적으로 올바르게 배치되지만 오른쪽에서 왼쪽으로 쓰는 텍스트 위에 여전히 "굵게"라고 읽는 도구 모음은 절반만 번역됩니다.
🏷 변수
자리 표시자를 삽입하기 위한 도구 모음 드롭다운을 추가합니다. 문서를 작성하는 사람이 이메일, 송장 또는 계약 템플릿과 같이 자리 표시자 구문을 정의한 개발자가 아닐 때 유용합니다. 읽을 수 있는 이름을 선택하면 올바른 구문이 삽입됩니다.
1 2 3 4 5 6 7 8 9 | new MarkdownEditor('#markdown-editor', { toolbar: ['bold', 'italic', 'link', { variables: [ { label: 'Customer Name', value: '{{customer.name}}' }, { label: 'Invoice No', value: '{{invoice.number}}' } ]}, 'preview' ] }); |
이 도구는 다음에서 인라인으로 구성됩니다. toolbar 배열하므로 다른 버튼 사이의 위치는 사용자에게 달려 있습니다. 버튼에는 라벨이 나열되며, 버튼을 클릭하면 해당 라벨이 삽입됩니다. value 커서에서 선택 항목을 대체합니다. 목록이 비어 있으면 아무것도 렌더링되지 않습니다.
미리보기의 샘플 값
주어진 항목 sample 미리보기에 해당 샘플을 표시하는 반면 텍스트 영역은 실제 자리 표시자를 유지합니다. 하나도 없는 항목은 작성된 대로 표시되므로 둘 다 혼합할 수 있습니다.
1 2 3 4 5 6 7 | { variables: [ { label: 'Customer Name', value: '{{customer.name}}', sample: 'Hannes' }, { label: 'Invoice No', value: '{{invoice.number}}' } ]} // textarea : Hi {{customer.name}}, invoice {{invoice.number}} // preview : Hi Hannes, invoice {{invoice.number}} |
그룹화
항목을 제공 items 대신에 value 표제 섹션을 렌더링합니다. 그룹화된 항목과 일반 항목을 하나의 목록에 혼합할 수 있습니다.
1 2 3 4 5 6 7 8 9 10 | { variables: [ { label: 'Today', value: '{{today}}', sample: '10 September 2026' }, { label: 'Customer', items: [ { label: 'Name', value: '{{customer.name}}', sample: 'Hannes' }, { label: 'Email', value: '{{customer.email}}', sample: 'hannes@example.com' } ]}, { label: 'Invoice', items: [ { label: 'Number', value: '{{invoice.number}}' } ]} ]} |
알아야 할 사항
- 편집기는 변수를 확인하지 않습니다. 텍스트를 삽입하고 응용 프로그램은 나중에 일반적으로 서버 측에서 실제 값을 대체합니다.
sample미리보기에 표시되는 내용에만 영향을 미칩니다. - 레이블은 일반 텍스트로 표시되므로 레이블의 마크업은 렌더링되지 않습니다.
- 잘못된 항목은 던지는 대신 건너뛰고 사용할 수 있는 항목이 구성되지 않으면 버튼이 전혀 렌더링되지 않습니다.
🖋 사용자 정의 렌더러
미리보기는 다음과 같이 렌더링됩니다. 두드러진 그리고 소독으로 DOMPurify. 둘 다 교체 가능합니다. 애플리케이션이 이미 다른 라이브러리를 사용하여 마크다운을 렌더링하고 미리보기가 프로덕션과 정확히 일치하도록 하려는 경우 이 기능을 사용하세요.
두 옵션 모두 문자열을 가져와 문자열을 반환하는 일반 함수이므로 모든 파서와 새니타이저가 작동합니다.
1 2 3 4 5 6 7 8 9 | import MarkdownIt from 'markdown-it'; import taskLists from 'markdown-it-task-lists'; import MarkdownEditor from 'markdown-text-editor'; const md = new MarkdownIt({ linkify: true, breaks: true }).use(taskLists); new MarkdownEditor('#markdown-editor', { renderer: markdown => md.render(markdown) }); |
DOMPurify는 여전히 출력에서 실행되므로 아무것도 구성하지 않고도 XSS 보호를 유지할 수 있습니다.
맞춤형 소독제
렌더러가 방출하는 것을 기본으로 제거할 때만 필요합니다. DOMPurify가 제거합니다. <iframe> 기본적으로 비디오 삽입에는 명시적으로 허용되어야 합니다. 편집기와 함께 번들로 제공되는 사본은 내부용이므로 DOMPurify는 자신의 코드로 가져와야 합니다.
1 2 3 4 5 6 7 8 9 | import DOMPurify from 'dompurify'; new MarkdownEditor('#markdown-editor', { renderer: markdown => md.render(markdown), sanitizer: html => DOMPurify.sanitize(html, { ADD_TAGS: ['iframe'], ADD_ATTR: ['allow', 'allowfullscreen', 'frameborder'] }) }); |
번들러 대신 스크립트 태그를 사용하여 편집기와 함께 DOMPurify를 로드합니다.
1 2 | <script src="https://cdn.jsdelivr.net/npm/dompurify"></script> <script src="https://cdn.jsdelivr.net/npm/markdown-text-editor"></script> |
알아야 할 사항
- 미리보기 전용. 하이브리드 모드의 라이브 포맷은 별도의 내부 렌더러를 사용하며 영향을 받지 않습니다.
- 작업 목록에는 플러그인 지원이 필요합니다. 클릭 가능한 확인란은 다음을 검색하여 찾을 수 있습니다.
input[type="checkbox"]출력에 마크다운이 필요합니다.markdown-it-task-lists. 편집기는 작업 목록 구문을 감지하고 확인란이 없으면 경고를 기록합니다. - 둘 다 동기식이어야 하며 문자열을 반환해야 합니다. 안
async함수 쓰기[object Promise]미리보기에 들어갑니다. - 소독제를 교체하면 보호 기능도 대체됩니다.
html => html삭제를 완전히 비활성화하고 완전히 신뢰할 수 있는 콘텐츠에만 안전합니다.
🎨 내부 요소 스타일링
CSS 변수는 상속되기 때문에 대부분의 테마를 다루므로 하나를 설정합니다. .markdown-editor-wrapper 도구 모음, 버튼, 미리 보기 및 바닥글에 도달합니다. 필요한 것을 노출하는 변수가 없는 경우에만 클래스 이름을 찾으세요.
1 2 3 4 5 | /* Variables set on the wrapper inherit down to every child */ .markdown-editor-wrapper { --border-radius: 12px; /* rounds the editor and its toolbar buttons */ --color-primary: oklch(60% 0.2 30); } |
수업 참고자료
이러한 클래스 이름은 안정적이고 스타일을 지정하기에 안전합니다.
| 수업 | 요소 |
|---|---|
.markdown-editor-wrapper | 전체 편집기를 감싸는 외부 컨테이너 |
.toolbar | 편집 영역 위의 도구 모음 스트립 |
.markdown-btn | 개별 도구 모음 버튼 |
.preview-btn | 미리보기/전체화면 토글 버튼 |
.editor-layout | 편집 영역과 미리보기를 나란히 유지하는 그리드 |
.textarea-wrapper | 편집 영역 주변의 래퍼 |
.editor-textarea | 기본 텍스트 영역 요소 |
.display-layer | 렌더링된 서식 레이어, 하이브리드 모드만 해당 |
.preview-wrapper | 미리보기 열 |
.preview-content | 미리보기 내부에 렌더링된 마크다운 |
.editor-footer | 편집기 아래 상태 표시줄 |
.find-replace-panel | 패널 찾기 및 바꾸기 |
1 2 3 4 5 6 7 8 9 10 | /* Some variables are set by the component on itself, which beats an inherited value. Target the element directly for those. */ .markdown-editor-wrapper .markdown-btn { --btn--font-size: 0.875rem; } /* And use classes for anything no variable exposes */ .markdown-editor-wrapper .toolbar { border-bottom: 2px solid oklch(60% 0.2 30); } |
편집자 한 명을 대상으로
한 페이지에 여러 편집자가 있으면 그 중 하나를 대상으로 지정하십시오. data-editor. 래퍼는 해당 ID를 반영합니다. <textarea>, 그래서 <textarea id="notes"> 당신에게 준다 [data-editor="notes"]. ID 자체는 텍스트 영역에 있으므로 getElementById 계속 작동합니다.
1 2 3 4 | /* one editor only */ [data-editor="notes"] { --border-radius: 0; } |
🪟 전체 화면 및 레이어링(z-색인)
전체 화면에서 편집기는 다음을 사용합니다. z-index: 10000, 이는 대부분의 UI 프레임워크가 고정 헤더 및 오버레이용으로 예약한 레이어를 지웁니다. 고정된 헤더나 사이드바가 여전히 편집기를 덮고 있는 경우 이 값을 높이세요.
다음으로 재정의하세요. --mte-fullscreen-z-index. 값은 전체 화면에서만 적용되고 상속되므로 상위 항목에 값을 설정하면 그 아래의 모든 편집기가 적용됩니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | /* every editor on the page */ .markdown-editor-wrapper { --mte-fullscreen-z-index: 20000; } /* one section only - the value inherits down */ #admin-panel { --mte-fullscreen-z-index: 20000; } /* a single editor, by its textarea id */ [data-editor="notes"] { --mte-fullscreen-z-index: 20000; } |
콘텐츠 API
MarkdownEditor의 핵심 강점 중 하나는 기본 내용을 유지한다는 것입니다. <textarea> 완벽하게 동기화되었습니다. 최신 JavaScript 프레임워크를 사용하든 Django, PHP 또는 Laravel과 같은 기존 백엔드를 사용하든 워크플로는 단순하고 기본적으로 유지됩니다.
콘텐츠 읽기 및 쓰기
1. 네이티브 방식(권장)
편집기는 표준 텍스트 영역을 향상시키기 때문에 친숙한 DOM 방법을 사용할 수 있습니다. 이는 새로운 API를 배우지 않고도 데이터와 상호 작용하는 가장 빠른 방법입니다.
1 2 3 4 5 | // Retrieve content via ID const markdown = document.getElementById('markdown-editor').value; // Set content via ID (The editor UI updates automatically) document.getElementById('markdown-editor').value = "# New Heading Content"; |
2. 변수 참조 사용
textarea 요소에 대한 참조가 있는 경우 이를 직접 사용할 수 있습니다. 라이브러리별 API가 필요하지 않습니다.
1 2 3 4 5 6 7 | const textarea = document.getElementById('markdown-editor'); // Retrieve content const markdown = textarea.value; // Set content (the editor UI reflects this immediately) textarea.value = "## Updated via JS"; |
3. 서버측 초기 콘텐츠 설정
초기 콘텐츠를 설정하는 권장 방법은 <textarea> HTML: 이는 모든 백엔드 프레임워크(Django, Laravel, Rails, PHP 등)에서 자연스럽게 작동하며 편집기는 초기화 시 자동으로 렌더링합니다.
1 2 | <!-- Recommended: set content server-side --> <textarea id="markdown-editor"># Hello World</textarea> |
런타임에 콘텐츠를 읽거나 업데이트하려면 기본 textarea 값. 부르다 editor.render() 업데이트 후 미리보기 및 하이브리드 레이어를 새로 고칩니다.
1 2 3 4 5 6 7 8 | const textarea = document.getElementById('markdown-editor'); // Read const markdown = textarea.value; // Update at runtime textarea.value = '# New content'; editor.render(); |
4. 편집기 분해: destroy()
부르다 editor.destroy() 편집기 DOM 래퍼를 제거하고 원본을 복원하려면 <textarea> 문서의 해당 위치로 이동합니다. 뷰를 마운트 해제할 때 단일 페이지 애플리케이션에 유용합니다.
1 2 3 4 | const editor = new MarkdownEditor('#markdown-editor'); // Remove the editor and restore the plain textarea editor.destroy(); |
변화에 대응하기 onChange
통과 onChange 콘텐츠가 변경될 때마다 알림을 받을 콜백입니다. 현재 마크다운 문자열을 받습니다.
1 2 3 4 5 | const editor = new MarkdownEditor('#markdown-editor', { onChange(value) { console.log('Content changed:', value.length, 'characters'); } }); |
초안 자동 저장 localStorage
사용 onChange 키를 누를 때마다 초안을 저장합니다. 편집기를 초기화하기 전에 텍스트 영역을 미리 채워서 복원하세요.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | const DRAFT_KEY = 'my-page-draft'; // Restore saved draft before init (only if textarea starts empty) const textarea = document.getElementById('markdown-editor'); const saved = localStorage.getItem(DRAFT_KEY); if (saved && !textarea.value) textarea.value = saved; // Save on every change const editor = new MarkdownEditor('#markdown-editor', { onChange(value) { localStorage.setItem(DRAFT_KEY, value); } }); // Clear draft after successful form submission document.querySelector('form').addEventListener('submit', () => { localStorage.removeItem(DRAFT_KEY); }); |
양식 제출
MarkdownEditor는 네이티브에 직접 구축되었기 때문입니다. <textarea>, 모든 백엔드 프레임워크(Django, Laravel, PHP, Ruby on Rails 등)와 즉시 호환됩니다.
'네이티브 퍼스트(Native-First)' 철학이 빛을 발하는 곳입니다. 양식을 제출하기 전에 데이터를 수동으로 동기화할 필요가 없습니다. 브라우저는 편집기를 표준 입력 필드와 똑같이 처리합니다.
1 2 3 4 5 6 7 8 9 10 11 12 | <form method="POST" action="/api/submit"> <textarea id="markdown-editor" name="content" class="h-48" rows="5"> # Initial Content </textarea> <button type="submit">Submit to Server</button> </form> <script> // Just initialize it. That's it. new MarkdownEditor('#markdown-editor'); </script> |
메모: MarkdownEditor 플러그인 초기화 필수
표준 HTML을 사용하세요. <form>. 그만큼 name 텍스트 영역의 속성은 서버가 콘텐츠를 식별하는 데 사용하는 것입니다.
🚀 이것이 백엔드의 판도를 바꾸는 이유
편집자는 네이티브를 유지하므로 <textarea> 동작하면 서버는 데이터를 표준 문자열로 처리합니다. 추가 논리가 필요하지 않습니다. 아니요 preventDefault() 그리고 매뉴얼도 없고 FormData 건설.
💡 이것이 "킬러 기능"인 이유:
대부분의 편집기(예: Quill, Editor.js, simpleMDE, easyMDE)는 데이터를 복잡한 JSON 구조로 저장합니다. 개발자가 이를 사용하는 경우 데이터베이스 스키마와 렌더링 논리를 다시 작성해야 합니다.
MarkdownEditor를 사용하면 개발자는 오래된 웹사이트를 일반 웹사이트로 대체할 수 있습니다. <textarea> 편집자와 함께 사용하면 백엔드는 변경된 사실조차 알지 못합니다. 항상 그랬던 것과 동일한 원시 텍스트를 수신하지만 사용자는 10배 더 나은 경험을 얻습니다.
| 프레임워크/언어 | 마크다운 콘텐츠에 액세스하는 방법 |
|---|---|
| PHP | $_POST['content'] |
| 장고 | request.POST.get('content') |
| Node.js(익스프레스) | req.body.content |
| 라라벨 | $request->input('content') |
| 루비 온 레일 | params[:content] |
🖼️ 고급 이미지 업로드
이미지 업로드를 기본적으로 처리하는 것은 느리고 메모리 사용량이 많은 Base64 문자열에 의존하는 대신 성능과 SEO 모두에 있어 상당한 이점입니다.
붙여넣고 놓기
스크린샷을 붙여넣거나 이미지 파일을 편집기로 드래그하면 도구 모음 버튼과 동일한 엔드포인트를 통해 업로드됩니다. 편집기가 정지된 것처럼 보이지 않도록 자리 표시자가 즉시 나타나며, 업로드가 완료되면 실제 경로로 대체됩니다. 업로드가 실패하면 자리 표시자는 자동으로 사라지지 않고 보이는 마커로 대체됩니다.
이 필요 uploadUrl 아래에 구성되었습니다. 그것이 없으면 이미지를 붙여넣어도 아무런 작업이 수행되지 않으며 편집기는 무엇을 추가할지 설명하는 경고를 기록합니다. 대안은 데이터베이스의 Base64 문자열이기 때문입니다.
여러 개의 파일이 한 번에 하나씩 업로드되므로 이미지는 도착한 순서대로 표시됩니다.
구성 옵션
이미지 도구는 다음을 지원합니다. fileInput 직접 서버 업로드를 처리하기 위한 구성입니다.
accept: 허용되는 이미지 형식의 배열을 정의합니다(예: 'webp', 'avif')uploadUrl: 백엔드 엔드포인트를 지정합니다.File개체는 다음을 통해 전송됩니다.POSTparams: 이미지 파일과 함께 추가 데이터(예: CSRF 토큰, 사용자 ID 또는 폴더 이름)를 보내는 선택적 개체입니다.
사용예(Full Config)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | const options = { placeholder: 'Start writing...', toolbar: [ 'link', { image: { fileInput: { accept: ['webp', 'avif'], // restrict the image upload format uploadUrl: '/api/upload', // Your upload endpoint params: { _token: 'your_csrf_token_here', // Essential for Laravel/Django folder: 'blog_posts' } }, // Supports boolean: true/false OR object: { required: true } altInput: { required: true } } }, 'preview' ], } const editor = new MarkdownEditor('#markdown-editor', options); |
📡 서버 통합
요청
편집자가 보낸다. POST 다음으로 요청 multipart/form-data. 기본적으로 다음이 포함됩니다.
image_file: 실제 파일 객체image_alt: 사용자가 입력한 대체 텍스트- ...그리고 여기에 정의된 모든 사용자 정의 데이터
params물체
필수 응답
성공적인 업로드를 확인하고 이미지를 편집기에 삽입하려면 서버가 반드시 다음 JSON 구조를 반환해야 합니다.
1 2 3 4 | { "success": true, "image_path": "https://cdn.yourdomain.com/uploads/image.webp" } |
참고: 키를 사용해야 합니다. image_path 업로드된 이미지의 URL입니다.
돌아올 수도 있습니다 image_alt, 이는 사용자가 대체 필드를 비워둔 경우에만 제안으로 사용됩니다. 사용자가 직접 입력한 내용은 항상 우선하므로 파일 이름이나 이미지 인식에서 대체 텍스트를 파생하는 서버는 실제 설명을 덮어쓰지 않고 이를 제공할 수 있습니다.
1 2 3 4 5 | { "success": true, "image_path": "https://cdn.yourdomain.com/uploads/image.webp", "image_alt": "Two people looking at a laptop" } |
실패시 복귀 success: false 와 error 또는 message 끈. 해당 텍스트는 사용자에게 표시되므로 사용자가 조치를 취할 수 있도록 만드세요.
이미지 대체 텍스트 유효성 검사(altInput)
콘텐츠에 대한 접근성과 SEO 친화적인 상태를 유지하기 위해 MarkdownEditor는 기본적으로 대체 텍스트 유효성 검사를 시행합니다.
- 기본 동작:
altInput정의되지 않았으며 기본값은 다음과 같습니다.{ required: true } - 접근성 강화: 대체 설명이 제공될 때까지 사용자는 이미지를 삽입할 수 없습니다.
1. 기본값(구성 필요 없음)
1 2 3 4 | // Alt text is REQUIRED by default image: { fileInput: { uploadUrl: '/api/upload' } } |
2. 속기(검증 비활성화)
설명 없이 이미지를 허용하려면 부울을 다음으로 설정하면 됩니다. false.
1 2 3 | image: { altInput: false // Users can now skip the alt text field } |
3. 객체 기반(명시적)
1 2 3 4 5 | image: { altInput: { required: false // Disables alt text validation — users can skip the alt field } } |
표준 이미지 사용(아니요 fileInput)
만약에 fileInput 구성되지 않은 경우 편집기는 기본적으로 단순 URL 기반 모달을 사용합니다. 이는 사용자가 주로 외부 이미지 호스트에 연결하는 경우에 이상적입니다.
1 2 3 4 5 6 7 8 | const options = { toolbar: [ 'link', 'image', 'preview' ], } const editor = new MarkdownEditor('#markdown-editor', options); |
💡 매개변수를 사용하는 이유는 무엇인가요?
Laravel 또는 Django와 같은 프레임워크에서는 CSRF 토큰 없이는 파일을 업로드할 수 없습니다. 추가하여 _token 에 params 개체가 있는 경우 귀하의 요청은 백엔드의 보안 미들웨어를 원활하게 통과하여 서버측 컨트롤러에 대한 "제로 로직" 철학을 유지합니다.
⌨️ 키보드 단축키
도구 모음을 터치하지 않고도 일반적인 서식 작업을 키보드에서 직접 실행할 수 있습니다. 각 단축키는 해당 도구 모음 버튼의 도구 설명에도 표시됩니다.
| 지름길 | 행동 |
|---|---|
Ctrl + B / ⌘ B | 굵게 전환 |
Ctrl + I / ⌘ I | 기울임꼴 전환 |
Ctrl + K / ⌘ K | 링크 삽입 |
Ctrl + ` / ⌘ ` | 인라인으로 전환 Code |
Ctrl + Shift + S / ⌘ ⇧ S | |
Ctrl + 1 / ⌘ 1 | 제목 1 |
Ctrl + 2 / ⌘ 2 | 제목 2 |
Ctrl + 3 / ⌘ 3 | 제목 3 |
Ctrl + L / ⌘ L | 글머리 기호 목록 전환 |
Ctrl + Z / ⌘ Z | 끄르다 |
Ctrl + Shift + Z / ⌘ ⇧ Z | 다시 하다 |
Tab | 선택한 줄 들여쓰기 |
Shift + Tab | 선택한 줄을 내어쓰기합니다. |
Ctrl + F / ⌘ F | 찾기 패널 열기 |
Ctrl + H / ⌘ H | 찾기 및 바꾸기 패널 열기 |
Ctrl + Shift + F / ⌘ ⇧ F | 전체 화면 미리보기 전환 |
F11 | 전체 화면 미리보기 전환 |
Escape | 찾기 패널 닫기/전체 화면 미리보기 종료 |
🔍 찾기 및 바꾸기
편집기 내에서 내장된 찾기 및 바꾸기 패널을 사용할 수 있습니다. 브라우저 확장이나 별도의 도구가 필요하지 않습니다.
- 누르다
Ctrl + F(또는⌘ F) 찾기 패널을 엽니다. - 누르다
Ctrl + H(또는⌘ H)를 눌러 찾기 및 바꾸기 패널을 엽니다. - 검색은 대소문자를 구분하지 않으며 실시간 일치 카운터를 표시합니다(예: 12개 중 3개)
- ▲ / ▼ 버튼을 사용하여 경기를 탐색하거나
Enter/Shift + Enter - 바꾸기는 현재 강조 표시된 일치 항목을 대체합니다. 모두 바꾸기는 모든 항목을 한 번에 바꿉니다.
- 누르다
Escape패널을 닫고 포커스를 편집기로 되돌리려면
패널은 편집기 콘텐츠 영역의 오른쪽 상단에 떠 있으며 쓰기를 방해하지 않습니다.
🔗 붙여넣은 URL의 링크
일부 텍스트를 선택하고 그 위에 URL을 붙여넣으면 선택한 내용을 대체하는 URL 대신 마크다운 링크가 표시됩니다.
1 2 | Read the docs <- select "the docs", paste https://example.com Read [the docs](https://example.com) <- what you get |
규칙은 의도적으로 엄격합니다. http 또는 https 공백이 없는 URL은 이런 방식으로 처리됩니다. 우연히 URL이 포함된 문장을 붙여넣거나 아무것도 선택하지 않고 붙여넣으면 일반 붙여넣기처럼 동작합니다.
특징
🔌 기본 양식 통합
표준과 정확히 동일하게 작동합니다. <textarea>. 복잡한 API가 없습니다. value 또는 name 기인하다. PHP, Django 또는 Node.js의 표준 HTML 양식 제출과 함께 "작동"합니다.
🖼️ 고급 이미지 업로드
API를 통해 기본 서버 업로드를 구성합니다. 자체 CDN에서 이미지를 호스팅하여 더 빠른 페이지 로드와 뛰어난 SEO를 보장하려면 무거운 Base64 문자열을 피하세요.
🔀 하이브리드 및 일반 모드
사이를 전환 하이브리드(WYSIWYG) 영상 편집 경험이 있거나 일반 마크다운 전통적인 코딩 느낌을 위한 모드입니다.
🚀 고성능
에이 gzip으로 압축된 53KB "무거운 콘텐츠"에 최적화된 번들(252KB 축소, CSS 포함)입니다. 입력 지연이나 성능 저하 없이 대용량 문서 및 대용량 파일을 처리합니다. 디바운스된 미리보기 업데이트, 캐시된 스타일 계산 및 충돌 없는 키보드 처리: 따라서 Tab과 Enter는 항상 정확히 한 가지 작업을 수행합니다.
🌍 내장 RTL 지원
아랍어, 우르두어, 페르시아어와 같은 오른쪽에서 왼쪽으로 쓰는 언어를 기본적으로 지원합니다. 전 세계적으로 액세스 가능한 애플리케이션을 구축하는 데 적합합니다.
✨ 구문 강조
명확한 코드와 마크다운 형식으로 가독성이 향상되었습니다.
🌙 적응형 테마
자동 다크 모드 지원이 포함됩니다. 시스템 설정 또는 프루트잼 UI 원활한 시각적 경험을 위한 라이브러리입니다.
📝 스마트 편집
정렬된 목록, 정렬되지 않은 목록 및 체크리스트에 대한 GitHub 스타일 자동 목록 연속: 누르기 Enter 편집자는 패턴을 계속합니다. 미리보기 창의 확인란을 클릭할 수 있으며 즉시 마크다운 소스에 다시 동기화됩니다.
📱 완전 반응형
이동 중에 편집할 수 있도록 데스크톱, 태블릿, 스마트폰에 완벽하게 적응하는 유연한 모바일 우선 UI입니다.
📦 범용 지원
호환 가능 ESM, UMD, CommonJS 및 IIFE. CDN을 통해 즉시 작동합니다(<script src>), npm 또는 모든 번들러(Vite, webpack, Rollup): 추가 구성이 필요하지 않습니다.
♿ 기본적으로 액세스 가능
전체 ARIA 지원 내장: 도구 모음 랜드마크, 레이블이 지정된 미리보기 영역, 화면 판독기 친화적인 버튼, aria-pressed 미리보기 토글에서 disabled 그리고 aria-disabled 비활성 도구에 대한 정보 및 모달이 닫힐 때 올바른 초점 복원.
🛡️ CSS 충돌 없음
편집기 스타일의 범위는 다음과 같습니다. .markdown-editor-wrapper. Tailwind의 전역 프리플라이트가 제외되므로 편집자는 스타일을 손상시키지 않고 Bootstrap, Tailwind 또는 기타 프레임워크와 함께 안전하게 사용할 수 있습니다.
⌨️ 키보드 단축키
Ctrl+B, Ctrl+I, Ctrl+K, Ctrl+`, Ctrl+Shift+S: 마우스를 건드리지 않고도 일반적인 서식 지정 작업을 수행할 수 있습니다. 각 단축키는 도구 모음 버튼의 도구 설명에 표시됩니다.
🔍 찾기 및 바꾸기
누르다 Ctrl+F 찾거나 Ctrl+H 찾기 및 바꾸기를 엽니다. 실시간 일치 카운터, 다음/이전 탐색, 단일 교체 및 모두 교체를 통한 대소문자 구분 검색: 편집기를 종료하지 않고도 가능합니다.
🔒 XSS 안전 미리보기
렌더링된 미리보기는 다음을 통해 삭제됩니다. DOMPurify DOM에 기록되기 전에. 조작된 마크다운 입력의 스크립트 태그, 인라인 이벤트 핸들러 및 악성 URL은 자동으로 제거됩니다. 구성이 필요하지 않습니다.
▶️ 실시간 미리보기
입력하는 즉시 렌더링된 마크다운을 확인하세요.
🔗 손쉬운 통합
최소한의 설정으로 모든 웹 프로젝트에 원활하게 통합됩니다.
🛠️ 사용자 정의 가능한 도구 모음
굵게, 기울임꼴 등과 같은 도구 모음 옵션을 동적으로 구성하고 순서를 변경합니다.
전체 구성 예
이 포괄적인 예제를 사용하여 사용자 정의 도구 모음 순서 및 고급 이미지 업로드 처리를 포함한 모든 기본 기능으로 MarkdownEditor를 초기화하세요.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | const editor = new MarkdownEditor('#markdown-editor', { mode: 'hybrid', placeholder: 'Start writing...', footer: { line: true, col: true, chars: true, words: true, }, onChange(value) { console.log('Content updated:', value.length, 'characters'); }, labels: { 'Bold': 'Gras', 'Italic': 'Italique', 'Uploading...': 'Téléversement...', }, toolbar: [ 'heading', 'bold', 'italic', 'strikethrough', 'blockquote', 'ul', 'ol', 'checklist', 'code', 'codeblock', 'hr', 'table', { image: { fileInput: { accept: ['webp', 'avif', 'png'], uploadUrl: '/api/upload' } } }, 'link', 'undo', 'redo', 'indent', 'outdent', 'preview' ], }); // Read content natively const markdown = document.getElementById('markdown-editor').value; // destroy() when the view unmounts (SPAs) // editor.destroy(); |
이것이 유용하다고 생각하시나요?
GitHub 스타는 다른 개발자가 편집기를 찾는 데 도움이 됩니다. 그것은의 일부입니다 프루잠. 거기에 있는 별도 도움이 됩니다.