React および Prosemirror ベースのエディターで、Outline を強化し、読み取り専用形式でコンテンツを表示するためにも使用できます。エディターは WYSIWYG であり、マークダウン ショートカットをインラインで記述し、プレーンなマークダウンを出力する機能を維持しながら、書式設定ツールが含まれています。ライブ デモのストーリーブックを参照してください。
重要な注意: このプロジェクトは、万能の Markdown エディターを目指しているわけではありません。これは、Outline ナレッジ ベース用に構築されており、他のユーザーがこのパッケージをフォークしたり、独自の製品で使用したりすることは歓迎されていますが、開発上の決定は、Outline のニーズを中心に行われます。
yarn add rich-markdown-editor
または
npm install rich-markdown-editor
react
、 react-dom
、およびstyled-components
必須のピア依存関係であることに注意してください。
import Editor from "rich-markdown-editor" ;
< Editor
defaultValue = "Hello world!"
/>
このリポジトリのクローンを作成し、 yarn start
で Storybook を実行すると、さまざまな使用例が表示されます。
id
このエディタの一意の ID。設定をローカル ストレージに保持するために使用されます。 id
が渡されない場合、エディターはデフォルトで場所のパス名を使用します。
defaultValue
エディターの初期値を表すマークダウン文字列。これを使用して、ユーザーが編集を続行できるように、以前に保存したコンテンツを復元します。
value
エディターの値を表すマークダウン文字列。このプロパティを使用して、マウントされたエディターの値を変更します。これにより、エディター全体が再レンダリングされるため、 readOnly
モードの場合にのみ適しています。 onChange
の値をパイプしてvalue
に戻さないでください。エディターは独自の内部状態を保持するため、予期しない副作用が発生します。
placeholder
プレースホルダーの上書きを許可します。デフォルトは「何か良いものを書いて…」です。
readOnly
readOnly
false
に設定すると、エディターは合成用に最適化されます。 true
の場合、エディターを使用して以前に作成したコンテンツを表示できます。見出しにアンカーが追加され、リンクをクリック可能になります。
readOnlyWriteCheckboxes
readOnlyWriteCheckboxes
をtrue
に設定すると、 readOnly
がtrue
に設定され、それ以外の場合はエディターを編集できませんが、特殊な場合としてチェックボックスをオンまたはオフにすることができます。
autoFocus
true
に設定し、 readOnly
false
に設定すると、ドキュメントの最後に自動的にフォーカスされます。
maxLength
設定すると、マークダウン構文を含まないドキュメント上の最大文字長が強制されます。
extensions
追加の Prosemirror プラグインを基になる Prosemirror インスタンスに渡すことができます。
disableExtensions
無効にする含まれる拡張機能名のリスト。対応するメニュー項目とコマンドを削除します。たとえば、斜体テキストとブロック引用符を無効にするには、 ["em", "blockquote"]
に設定します。
theme
内蔵テーマをオーバーライドしてエディターをブランド化できます。たとえば、独自のフォントフェイスとブランドカラーを使用してエディターをアプリケーション内に適合させることができます。提供する必要があるキーの例については、組み込みテーマを参照してください。
dictionary
エディターを国際化するなど、組み込みのコピー辞書をオーバーライドできるようにします。提供する必要があるキーの例については、組み込みの辞書を参照してください。
dark
dark
true
に設定すると、エディターは含まれているデフォルトのダーク テーマを使用します。ソースはこちらをご覧ください。
dir
デフォルト: auto
ドキュメントの方向を制御します。可能な値は次のとおりです。
ltr
: エディターのレイアウトは LTR ドキュメント用に最適化されており、コンテンツは明示的に LTR としてマークされます。rtl
: エディターのレイアウトは RTL ドキュメント用に最適化されており、コンテンツは明示的に RTL としてマークされます。auto
: エディターのレイアウトは、ドキュメントの内容に基づいてブラウザーによって決定されます。 tooltip
オプションのツールチップを持つアイテムの周囲にラップされる React コンポーネント。これを使用して、独自のツールチップ ライブラリをエディターに挿入できます。コンポーネントには次の props が渡されます。
tooltip
: ツールチップコンテンツを含む React ノードplacement
: 列挙型のtop
、 bottom
、 left
、 right
children
: ツールチップがラップするコンポーネントをレンダリングする必要があります。 headingsOffset
ドキュメントの見出しをレベル数だけオフセットする数値。たとえば、メインのh1
タイトルの下にエディタをすでにネストしている場合、ユーザーがh2
見出し以下のみを作成できるようにしたい場合があります。この場合は、prop を1
に設定します。
scrollTo
見出しアンカーを表す文字列。見出しがビューポートに表示されるようにドキュメントがスムーズにスクロールします。
embeds
必要に応じて、 matcher
関数が真の値を返したときにリンクの代わりに挿入される埋め込みを定義します。 matcher メソッドの戻り値は、 props.attrs.matches
の下のコンポーネントで使用できます。 title
とicon
が指定されている場合、埋め込みはブロック メニューにも表示されます。
< Editor
embeds = { [
{
title : "Google Doc" ,
keywords : "google docs gdocs" ,
icon : < GoogleDocIcon /> ,
defaultHidden : false ,
matcher : href => href . matches ( / docs.google.com / i ) ,
component : GoogleDocEmbed
}
] }
/>
uploadImage(file: Blob): Promise<string>
エディターで画像をサポートしたい場合は、このコールバックを提供する必要があります。コールバックは単一のFile
オブジェクトを受け入れ、画像が保存場所 (S3 など) にアップロードされたときに URL に解決される Promise を返す必要があります。例えば:
< Editor
uploadImage = { async file => {
const result = await s3 . upload ( file ) ;
return result . url ;
} }
/>
onBlur(): void
このコールバックは、ユーザーがエディターの contenteditable およびブロック メニューやフローティング ツールバーなどのすべての関連 UI 要素へのフォーカスを失ったときにトリガーされます。 contenteditable 領域のみでブラー イベントをリッスンしたい場合は、 handleDOMEvents
プロパティを使用します。
onFocus(): void
このコールバックは、ユーザーがエディターの contenteditable またはブロック メニューやフローティング ツールバーなどの関連する UI 要素にフォーカスを置いたときにトリガーされます。 contenteditable 領域のみでフォーカス イベントをリッスンしたい場合は、 handleDOMEvents
プロパティを使用します。
onSave({ done: boolean }): void
このコールバックは、ユーザーがキーボード ショートカットCmd+S
またはCmd+Enter
使用して保存を明示的に要求したときにトリガーされます。これを信号として使用して、ドキュメントをリモート サーバーに保存できます。
onCancel(): void
このコールバックは、エディター内でCmd+Escape
が押されたときにトリガーされます。編集をキャンセルするために使用できます。
onChange(() => value): void
このコールバックは、通常はキーストロークなどのユーザー入力や書式設定オプションの使用によってエディターの内容が変更されたときにトリガーされます。これを使用して、エディターの状態をローカルに永続化できます。
呼び出されたときにドキュメントの現在のテキスト値を返す関数を返します。この最適化は、変更イベントごとにドキュメントの状態をテキストにシリアル化することを回避し、シリアル化された値が必要なタイミングをホスト アプリが選択できるようにするために行われます。
onImageUploadStart(): void
このコールバックは、 uploadImage
前にトリガーされ、アップロードが進行中であることを示す UI を表示するために使用できます。
onImageUploadStop(): void
画像のアップロードが成功または失敗するとトリガーされます。
onSearchLink(term: string): Promise<{ title: string, subtitle?: string, url: string }[]>
エディターには、書式設定ツールバーから挿入するリンクを検索する機能が用意されています。このコールバックが提供される場合、検索語を唯一のパラメータとして受け入れ、オブジェクトの配列に解決される Promise を返す必要があります。例えば:
< Editor
onSearchLink = { async searchTerm => {
const results = await MyAPI . search ( searchTerm ) ;
return results . map ( result => {
title : result . name ,
subtitle : `Created ${ result . createdAt } ` ,
url : result . url
} )
} }
/>
onCreateLink(title: string): Promise<string>
エディターには、オンザフライでドキュメントを作成するための書式設定ツールバーからリンクを作成する機能が用意されています。このコールバックが提供される場合、リンク「タイトル」を唯一のパラメータとして受け入れ、作成されたリンクの URL に解決される Promise を返す必要があります。例:
< Editor
onCreateLink = { async title => {
const url = await MyAPI . create ( {
title
} ) ;
return url ;
} }
/>
onShowToast(message: string, type: ToastType): void
エディターがユーザーにメッセージを表示したいときにトリガーされます。アプリの通知システムに接続するか、単純にwindow.alert(message)
を使用します。 2 番目のパラメータはトーストのタイプです: 'error' または 'info'。
onClickLink(href: string, event: MouseEvent): void
このコールバックにより、リンク処理をオーバーライドできます。外部リンクには新しいウィンドウを開かせ、内部リンクにはreact-router
などを使用してナビゲートさせたい場合がよくあります。コールバックが提供されない場合、新しいタブを開くデフォルトの動作がすべてのリンクに適用されます。例えば:
import { history } from "react-router" ;
< Editor
onClickLink = { ( href , event ) => {
if ( isInternalLink ( href ) ) {
history . push ( href ) ;
} else {
window . location . href = href ;
}
} }
/>
onHoverLink(event: MouseEvent): boolean
このコールバックにより、ユーザーがドキュメント内のリンク上にマウスを移動したことを検出できるようになります。
< Editor
onHoverLink = { event => {
console . log ( `Hovered link ${ event . target . href } ` ) ;
} }
/>
onClickHashtag(tag: string, event: MouseEvent): void
このコールバックにより、ドキュメント テキスト内のハッシュタグをクリックする処理が可能になります。コールバックが提供されない場合、ハッシュタグは通常のテキストとしてレンダリングされるため、このプロパティを渡すことでハッシュタグをサポートするかどうかを選択できます。
import { history } from "react-router" ;
< Editor
onClickHashtag = { tag => {
history . push ( `/hashtags/ ${ tag } ` ) ;
} }
/>
handleDOMEvents: {[name: string]: (view: EditorView, event: Event) => boolean;}
このオブジェクトは、イベント名 ( focus
、 paste
、 touchstart
など) をコールバック関数にマップします。
< Editor
handleDOMEvents = { {
focus : ( ) => console . log ( "FOCUS" ) ,
blur : ( ) => console . log ( "BLUR" ) ,
paste : ( ) => console . log ( "PASTE" ) ,
touchstart : ( ) => console . log ( "TOUCH START" ) ,
} }
/>
Editor コンポーネントは、マウントされたエディターと対話するためのメソッドをいくつか公開します。
focusAtStart(): void
文書の先頭にカーソルを置き、フォーカスを合わせます。
focusAtEnd(): void
文書の末尾にカーソルを置き、フォーカスを合わせます。
getHeadings(): { title: string, level: number, id: string }[]
ドキュメント内のすべての見出しのテキスト内容、階層内のレベル、およびアンカー ID を含むオブジェクトの配列を返します。 v10 ではtoc
オプションが削除されたため、これは独自の目次を作成するのに便利です。
このプロジェクトでは、糸を使用して依存関係を管理します。 npm を使用することもできますが、yarn lock ファイルは考慮されず、わずかに異なるバージョンがインストールされる可能性があります。
yarn install
開発で実行する場合、Storybook はホット リロードを備えたサンプル エディターに含まれます。依存関係をインストールしたら、 yarn start
。
yarn link
使用して開発する場合、 yarn watch
使用して、変更を加えるたびにdist
への変更を継続的に再構築できます。
このプロジェクトは BSD ライセンスを取得しています。