Ein auf React und Prosemirror basierender Editor, der Outline unterstützt und auch zum schreibgeschützten Anzeigen von Inhalten verwendet werden kann. Der Editor ist WYSIWYG und enthält Formatierungswerkzeuge, bietet aber weiterhin die Möglichkeit, Markdown-Verknüpfungen inline zu schreiben und einfachen Markdown auszugeben. Sehen Sie sich das Live-Demo-Storybook an.
Wichtiger Hinweis: Dieses Projekt soll kein Allzweck-Markdown-Editor sein . Es wurde für die Outline-Wissensdatenbank entwickelt, und während andere dieses Paket gerne abzweigen oder in Ihren eigenen Produkten verwenden können, konzentrieren sich Entwicklungsentscheidungen auf die Bedürfnisse von Outline.
yarn add rich-markdown-editoroder
npm install rich-markdown-editor Beachten Sie, dass react , react-dom und styled-components erforderliche Peer-Abhängigkeiten sind.
import Editor from "rich-markdown-editor" ;
< Editor
defaultValue = "Hello world!"
/> Klonen Sie dieses Repo und führen Sie das Storybook mit yarn start aus, um eine Vielzahl von Anwendungsbeispielen zu sehen.
id Eine eindeutige ID für diesen Editor, die zum Beibehalten von Einstellungen im lokalen Speicher verwendet wird. Wenn keine id übergeben wird, verwendet der Editor standardmäßig den Pfadnamen des Standorts.
defaultValueEine Markdown-Zeichenfolge, die den Anfangswert des Editors darstellt. Verwenden Sie dies, um zuvor gespeicherte Inhalte wiederherzustellen, damit der Benutzer die Bearbeitung fortsetzen kann.
value Eine Markdown-Zeichenfolge, die den Wert des Editors darstellt. Verwenden Sie diese Requisite, um den Wert des Editors nach dem Mounten zu ändern. Dadurch wird der gesamte Editor neu gerendert und ist daher nur im readOnly Modus geeignet. Leiten Sie den Wert von onChange nicht zurück in value weiter, da der Editor seinen eigenen internen Status behält und dies zu unerwarteten Nebenwirkungen führt.
placeholderErmöglicht das Überschreiben des Platzhalters. Die Standardeinstellung ist „Schreibe etwas Schönes…“.
readOnly Wenn readOnly auf false gesetzt ist, ist der Editor für die Komposition optimiert. Bei true kann der Editor verwendet werden, um zuvor geschriebene Inhalte anzuzeigen – Überschriften erhalten Anker und Links werden anklickbar.
readOnlyWriteCheckboxes Wenn readOnlyWriteCheckboxes auf true gesetzt ist, können Kontrollkästchen als Sonderfall weiterhin aktiviert oder deaktiviert werden, während readOnly auf true gesetzt ist und der Editor ansonsten nicht bearbeitet werden kann.
autoFocus Wenn true zusammen mit readOnly auf false gesetzt ist, wird der Fokus automatisch auf das Ende des Dokuments gesetzt.
maxLengthWenn diese Einstellung festgelegt ist, wird eine maximale Zeichenlänge für das Dokument erzwungen, ohne Markdown-Syntax.
extensionsErmöglicht die Übergabe zusätzlicher Prosemirror-Plugins an die zugrunde liegende Prosemirror-Instanz.
disableExtensions Liste der enthaltenen Erweiterungsnamen, die deaktiviert werden sollen. Entfernt entsprechende Menüelemente und Befehle. Setzen Sie ihn beispielsweise auf ["em", "blockquote"] um kursiven Text und Blockzitate zu deaktivieren.
themeErmöglicht das Überschreiben des integrierten Designs, um den Editor zu kennzeichnen. Verwenden Sie beispielsweise Ihre eigene Schriftart und Markenfarben, damit der Editor in Ihre Anwendung passt. Ein Beispiel für die Schlüssel, die bereitgestellt werden sollten, finden Sie im integrierten Design.
dictionaryErmöglicht das Überschreiben des integrierten Kopierwörterbuchs, um beispielsweise den Editor zu internationalisieren. Ein Beispiel für die Schlüssel, die bereitgestellt werden sollten, finden Sie im integrierten Wörterbuch.
dark Wenn dark auf true gesetzt ist, verwendet der Editor ein standardmäßiges dunkles Design, das enthalten ist. Die Quelle finden Sie hier.
dir Standard: auto
Steuert die Richtung des Dokuments. Mögliche Werte sind:
ltr : Das Editor-Layout ist für LTR-Dokumente optimiert und der Inhalt ist explizit als LTR gekennzeichnet.rtl : Das Editor-Layout ist für RTL-Dokumente optimiert und der Inhalt ist explizit als RTL gekennzeichnet.auto : Das Editor-Layout wird vom Browser basierend auf dem Dokumentinhalt festgelegt. tooltipEine React-Komponente, die um Elemente gewickelt wird, die über einen optionalen Tooltip verfügen. Damit können Sie Ihre eigene Tooltip-Bibliothek in den Editor einfügen – der Komponente werden die folgenden Requisiten übergeben:
tooltip : Ein React-Knoten mit dem Tooltip-Inhaltplacement : Aufzählung top , bottom , left , rightchildren : Die Komponente, die der Tooltip umschließt, muss gerendert werden headingsOffset Eine Zahl, die die Dokumentüberschriften um mehrere Ebenen versetzt. Wenn Sie den Editor beispielsweise bereits unter einem h1 Haupttitel verschachteln, möchten Sie möglicherweise, dass der Benutzer nur h2 Überschriften und darunter erstellen kann. In diesem Fall würden Sie die Requisite auf 1 setzen.
scrollToEine Zeichenfolge, die einen Überschriftenanker darstellt – das Dokument führt einen sanften Bildlauf durch, sodass die Überschrift im Ansichtsfenster sichtbar ist.
embeds Definieren Sie optional Einbettungen, die anstelle von Links eingefügt werden, wenn die matcher -Funktion einen wahrheitsgetreuen Wert zurückgibt. Der Rückgabewert der Matcher-Methode ist in der Komponente unter props.attrs.matches verfügbar. Wenn title und icon angegeben werden, erscheint die Einbettung auch im Blockmenü.
< 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> Wenn Sie möchten, dass der Editor Bilder unterstützt, muss dieser Rückruf bereitgestellt werden. Der Rückruf sollte ein einzelnes File akzeptieren und ein Versprechen zurückgeben, das in eine URL aufgelöst wird, wenn das Bild an einen Speicherort, beispielsweise S3, hochgeladen wurde. z.B:
< Editor
uploadImage = { async file => {
const result = await s3 . upload ( file ) ;
return result . url ;
} }
/> onBlur(): void Dieser Rückruf wird ausgelöst, wenn der Benutzer den Fokus auf den Editor contenteditable und alle zugehörigen UI-Elemente wie das Blockmenü und schwebende Symbolleisten verliert. Wenn Sie nur im inhaltsbearbeitbaren Bereich auf Unschärfeereignisse warten möchten, verwenden Sie handleDOMEvents Requisiten.
onFocus(): void Dieser Rückruf wird ausgelöst, wenn der Benutzer den Fokus auf den Editor contenteditable oder alle zugehörigen UI-Elemente wie das Blockmenü oder schwebende Symbolleisten richtet. Wenn Sie nur im inhaltsbearbeitbaren Bereich auf Fokusereignisse warten möchten, verwenden Sie handleDOMEvents Requisiten.
onSave({ done: boolean }): void Dieser Rückruf wird ausgelöst, wenn der Benutzer explizit das Speichern über die Tastenkombination Cmd+S oder Cmd+Enter anfordert. Sie können dies als Signal verwenden, um das Dokument auf einem Remote-Server zu speichern.
onCancel(): void Dieser Rückruf wird ausgelöst, wenn im Editor Cmd+Escape gedrückt wird. Sie können damit die Bearbeitung abbrechen.
onChange(() => value): voidDieser Rückruf wird ausgelöst, wenn sich der Inhalt des Editors ändert, normalerweise aufgrund von Benutzereingaben wie einem Tastendruck oder der Verwendung von Formatierungsoptionen. Sie können dies verwenden, um den Editorstatus lokal beizubehalten.
Es gibt eine Funktion zurück, die beim Aufruf den aktuellen Textwert des Dokuments zurückgibt. Diese Optimierung wird vorgenommen, um zu vermeiden, dass der Status des Dokuments bei jedem Änderungsereignis in Text umgewandelt wird, sodass die Host-App auswählen kann, wann sie den serialisierten Wert benötigt.
onImageUploadStart(): void Dieser Rückruf wird vor uploadImage ausgelöst und kann verwendet werden, um eine Benutzeroberfläche anzuzeigen, die anzeigt, dass ein Upload ausgeführt wird.
onImageUploadStop(): voidWird ausgelöst, sobald ein Bild-Upload erfolgreich war oder fehlgeschlagen ist.
onSearchLink(term: string): Promise<{ title: string, subtitle?: string, url: string }[]>Der Editor bietet die Möglichkeit, nach Links zu suchen, die über die Formatierungssymbolleiste eingefügt werden können. Wenn dieser Rückruf bereitgestellt wird, sollte er einen Suchbegriff als einzigen Parameter akzeptieren und ein Versprechen zurückgeben, das in ein Array von Objekten aufgelöst wird. z.B:
< 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>Der Editor bietet die Möglichkeit, Links über die Formatierungssymbolleiste zu erstellen, um Dokumente im Handumdrehen zu erstellen. Wenn dieser Rückruf bereitgestellt wird, sollte er einen Link-„Titel“ als einzigen Parameter akzeptieren und ein Versprechen zurückgeben, das in eine URL für den erstellten Link aufgelöst wird, z. B.:
< Editor
onCreateLink = { async title => {
const url = await MyAPI . create ( {
title
} ) ;
return url ;
} }
/> onShowToast(message: string, type: ToastType): void Wird ausgelöst, wenn der Editor dem Benutzer eine Nachricht anzeigen möchte. Schließen Sie sich an das Benachrichtigungssystem Ihrer App an oder verwenden Sie ganz einfach window.alert(message) . Der zweite Parameter ist die Art des Toasts: „error“ oder „info“.
onClickLink(href: string, event: MouseEvent): void Dieser Rückruf ermöglicht das Überschreiben der Linkbehandlung. Es ist oft der Fall, dass Sie möchten, dass externe Links ein neues Fenster öffnen und interne Links so etwas wie react-router zum Navigieren verwenden. Wenn kein Rückruf bereitgestellt wird, gilt für alle Links das Standardverhalten beim Öffnen eines neuen Tabs. z.B:
import { history } from "react-router" ;
< Editor
onClickLink = { ( href , event ) => {
if ( isInternalLink ( href ) ) {
history . push ( href ) ;
} else {
window . location . href = href ;
}
} }
/> onHoverLink(event: MouseEvent): booleanDieser Rückruf ermöglicht die Erkennung, wenn der Benutzer mit der Maus über einen Link im Dokument fährt.
< Editor
onHoverLink = { event => {
console . log ( `Hovered link ${ event . target . href } ` ) ;
} }
/> onClickHashtag(tag: string, event: MouseEvent): voidDieser Rückruf ermöglicht die Handhabung des Klickens auf Hashtags im Dokumenttext. Wenn kein Rückruf bereitgestellt wird, werden Hashtags als normaler Text gerendert, sodass Sie durch Übergabe dieser Requisite auswählen können, ob sie unterstützt werden sollen oder nicht.
import { history } from "react-router" ;
< Editor
onClickHashtag = { tag => {
history . push ( `/hashtags/ ${ tag } ` ) ;
} }
/> handleDOMEvents: {[name: string]: (view: EditorView, event: Event) => boolean;} Dieses Objekt ordnet Ereignisnamen ( focus , paste , touchstart usw.) Callback-Funktionen zu.
< Editor
handleDOMEvents = { {
focus : ( ) => console . log ( "FOCUS" ) ,
blur : ( ) => console . log ( "BLUR" ) ,
paste : ( ) => console . log ( "PASTE" ) ,
touchstart : ( ) => console . log ( "TOUCH START" ) ,
} }
/>Die Editor-Komponente stellt einige Methoden für die Interaktion mit dem bereitgestellten Editor bereit.
focusAtStart(): voidPlatzieren Sie den Cursor am Anfang des Dokuments und fokussieren Sie ihn.
focusAtEnd(): voidPlatzieren Sie den Cursor am Ende des Dokuments und fokussieren Sie ihn.
getHeadings(): { title: string, level: number, id: string }[] Gibt ein Array von Objekten mit dem Textinhalt aller Überschriften im Dokument, ihrer Ebene in der Hierarchie und der Anker-ID zurück. Dies ist nützlich, um Ihr eigenes Inhaltsverzeichnis zu erstellen, da die toc -Option in Version 10 entfernt wurde.
Dieses Projekt verwendet Garn, um Abhängigkeiten zu verwalten. Sie können npm verwenden, es berücksichtigt jedoch nicht die Garnsperrdatei und installiert möglicherweise leicht unterschiedliche Versionen.
yarn install
Bei der Ausführung in der Entwicklung ist Storybook mit Hot-Reloading in Beispieleditoren integriert. Führen Sie nach der Installation der Abhängigkeiten yarn start aus, um loszulegen.
Wenn Sie bei der Entwicklung mit yarn link arbeiten, können Sie yarn watch verwenden, um Änderungen kontinuierlich in dist umzuwandeln, während Sie Änderungen vornehmen.
Dieses Projekt ist BSD-lizenziert.