Rich text editor for Flutter

Overview

A rich text editor for Flutter

MIT License PRs Welcome Watch on GitHub Star on GitHub Watch on GitHub

FlutterQuill is a rich text editor and a Quill component for Flutter.

This library is a WYSIWYG editor built for the modern mobile platform, with web compatibility under development. You can join our Slack Group for discussion.

Demo App: https://bulletjournal.us/home/index.html

Pub: https://pub.dev/packages/flutter_quill

Usage

See the example directory for a minimal example of how to use FlutterQuill. You typically just need to instantiate a controller:

QuillController _controller = QuillController.basic();

and then embed the toolbar and the editor, within your app. For example:

Column(
  children: [
    QuillToolbar.basic(controller: _controller),
    Expanded(
      child: Container(
        child: QuillEditor.basic(
          controller: _controller,
          readOnly: false, // true for view only mode
        ),
      ),
    )
  ],
)

Check out Sample Page for advanced usage.

Input / Output

This library uses Quill as an internal data format.

  • Use _controller.document.toDelta() to extract the deltas.
  • Use _controller.document.toPlainText() to extract plain text.

FlutterQuill provides some JSON serialisation support, so that you can save and open documents. To save a document as JSON, do something like the following:

var json = jsonEncode(_controller.document.toDelta().toJson());

You can then write this to storage.

To open a FlutterQuill editor with an existing JSON representation that you've previously stored, you can do something like this:

var myJSON = jsonDecode(incomingJSONText);
_controller = QuillController(
          document: Document.fromJson(myJSON),
          selection: TextSelection.collapsed(offset: 0));

Configuration

The QuillToolbar class lets you customise which formatting options are available. Sample Page provides sample code for advanced usage and configuration.

Web

For web development, use flutter config --enable-web for flutter and use ReactQuill for React.

It is required to provide EmbedBuilder, e.g. defaultEmbedBuilderWeb. Also it is required to provide webImagePickImpl, e.g. Sample Page.

Desktop

It is required to provide filePickImpl for toolbar image button, e.g. Sample Page.

Custom Size Image for Mobile

Define mobileWidth, mobileHeight, mobileMargin, mobileAlignment as follows:

{
      "insert": {
         "image": "https://user-images.githubusercontent.com/122956/72955931-ccc07900-3d52-11ea-89b1-d468a6e2aa2b.png"
      },
      "attributes":{
         "style":"mobileWidth: 50; mobileHeight: 50; mobileMargin: 10; mobileAlignment: topLeft"
      }
}

Translation of toolbar

The package offers translations for the quill toolbar, it will follow the system locale unless you set your own locale with:

QuillToolbar(locale: Locale('fr'), ...)

Currently, translations are available for these locales:

  • Locale('en')
  • Locale('ar')
  • Locale('de')
  • Locale('da')
  • Locale('fr')
  • Locale('zh', 'CN')
  • Locale('ko')
  • Locale('ru')
  • Locale('es')
  • Locale('tr')
  • Locale('uk')

Contributing to translations

The translation file is located at lib/src/translations/toolbar.i18n.dart. Feel free to contribute your own translations, just copy the English translations map and replace the values with your translations. Then open a pull request so everyone can benefit from your translations!


1 1

1 1

Sponsors

Comments
  • how to get First image link from QuillEditor  ?

    how to get First image link from QuillEditor ?

    Hi, I just want to get the first image link from the data that the user entered in quillEditor. My app stores images in device storage using the path provider package. I printed the data and got this insert⟨ {image: /data/user/0/com.example.notes/app_flutter/image_picker8603960138221828112.jpg} ⟩

    but don't know how to get the first image link from this line. is there any idea?

    opened by MaheshManoharan 58
  • Support conversion of Delta to HTML and Markdown

    Support conversion of Delta to HTML and Markdown

    This Library converts Zeyfr documents to HTML. There are many plugins that can help with the conversion of HTML to markdown. I was thinking that with some tweaking we can create our own converter too.

    Or we can take another approach, we can first convert Delta to markdown like here and then to HTML. Again, this requires just some minor tweaking.

    enhancement 
    opened by ArjanAswal 45
  • How to add custom Text Styles, Embed images from device storage?

    How to add custom Text Styles, Embed images from device storage?

    I am porting my app from Zeyfr Editor to this wonderful plugin and I am stuck with a couple of problems.

    1] How can I add custom styles to the text. I looked at QuillStyles() but didn't understand anything.

    2] Whenever I open Notus document files (created by Zeyfr) with your package, it shows an error : Invalid argument (key "heading" not found.): "heading". Any idea how to fix it?

    3] How can I embed images from device storage? My current implementation (not working) is this :

    Future<String> uploadImageCallBack(File file) async {
        if (file == null) return null;
        return file.path;
    }
    

    Again Thank you for this wonderful package.

    opened by ArjanAswal 43
  • Get and set the reading reading position of the editor

    Get and set the reading reading position of the editor

    What is the best way to get (and then later set again) the current position the user has scrolled to? I have very long texts in my app and when the user starts reading, then closes the app and reopens it later again, the app should have "remembered" the reading progress and automatically scroll to the last position. So in other words I need something like an index of the current visible part of the text. Such a thing as the scroll position in pixels is not sufficient, because this would only be correct again on the same device, but e.g. wrong on the other devices of the user (the reading progress will be saved in the cloud in order to allow seamless reading across multiple devices). An answer would be highly appreciated.

    opened by FelixMittermeier 38
  • Newline character (

    Newline character ("\n") takes a lot of space.

    The newline character takes a lot of space and fills the entire screen pretty quickly. In my opinion it should take as much space as the normal line in a paragraph does. Right now it is taking twice as much.

    opened by ArjanAswal 25
  • [Feature Request] Maths Support

    [Feature Request] Maths Support

    I was wondering if it was possible to add maths support with LATEX? This plugin could be quite good to implement something like that.

    I'd be happy to do it myself, but I'm not too sure how to add a new element to the page UI. I skimmed through the documentation but it wasn't quite clear, would I start with the text_block.dart file?

    Thank you very much!! :)

    opened by garv-shah 24
  •  Error: The non-abstract class 'RawEditorState' is missing implementations for these members:

    Error: The non-abstract class 'RawEditorState' is missing implementations for these members:

    Stack trace:

    Launching lib/main-dev.dart on Google Pixel 3 in debug mode...
    ../../../../flutter/.pub-cache/hosted/pub.dartlang.org/flutter_quill-1.0.2/lib/widgets/raw_editor.dart:112:7: Error: The non-abstract class 'RawEditorState' is missing implementations for these members:
     - TextSelectionDelegate.userUpdateTextEditingValue                     
    Try to either                                                           
     - provide an implementation,                                           
     - inherit an implementation from a superclass or mixin,                
     - mark the class as abstract, or                                       
     - provide a 'noSuchMethod' implementation.                             
                                                                            
    class RawEditorState extends EditorState                                
          ^^^^^^^^^^^^^^                                                    
    ../../../../flutter/packages/flutter/lib/src/services/text_input.dart:822:8: Context: 'TextSelectionDelegate.userUpdateTextEditingValue' is defined here.
      void userUpdateTextEditingValue(TextEditingValue value, SelectionChangedCause cause);
           ^^^^^^^^^^^^^^^^^^^^^^^^^^                                       
    ../../../../flutter/.pub-cache/hosted/pub.dartlang.org/flutter_quill-1.0.2/lib/widgets/raw_editor.dart:1019:8: Error: The method 'RawEditorState.hideToolbar' has fewer positional arguments than those of overridden method 'TextSelectionDelegate.hideToolbar'.
      void hideToolbar() {                                                  
           ^                                                                
    ../../../../flutter/packages/flutter/lib/src/services/text_input.dart:829:8: Context: This is the overridden method ('hideToolbar').
      void hideToolbar([bool hideHandles = true]);                          
           ^                                                                
                                                                            
                                                                            
    FAILURE: Build failed with an exception.                                
                                                                            
    * Where:                                                                
    Script '/home/mehrdad/flutter/packages/flutter_tools/gradle/flutter.gradle' line: 1029
                                                                            
    * What went wrong:                                                      
    Execution failed for task ':app:compileFlutterBuildDevDebug'.           
    > Process 'command '/home/mehrdad/flutter/bin/flutter'' finished with non-zero exit value 1
                                                                            
    * Try:                                                                  
    Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
                                                                            
    * Get more help at https://help.gradle.org                              
                                                                            
    BUILD FAILED in 1m 45s
    

    pubspec.yml
    flutter_quill: ^1.0.2

    flutter doctor

    ▶ flutter doctor
    Doctor summary (to see all details, run flutter doctor -v):
    [✓] Flutter (Channel master, 2.1.0-11.0.pre.145, on Linux, locale en_US.UTF-8)
    [✓] Android toolchain - develop for Android devices (Android SDK version 30.0.0-rc2)
    [✓] Chrome - develop for the web
    [✓] Android Studio (version 3.6)
    [✓] IntelliJ IDEA Ultimate Edition (version 2020.3)
    [✓] IntelliJ IDEA Ultimate Edition (version 2020.2)
    [✓] VS Code (version 1.54.1)
    [✓] Connected device (2 available)
    
    • No issues found!
    
    
    
    opened by mehrdad-shokri 24
  • High dependency count

    High dependency count

    Firstly thank you very much for this plugin, it is awesome!

    The embedded blocks are great features, but supporting them does add a significant overhead to the app (>2mb in android apk size and ~20 dependencies). It would be nice to have a way to reduce this overhead for apps that don't need these advanced features, but I'm aware this is easier said than done (and would be a major breaking change).

    My proposal for this would be:

    • Split the plugin into two plugins, a 'core' package and a 'embeds' package
    • To use the full-featured option, a user would have to either add an extra parameter to their use of quill to load the extra widgets, or maybe there could be a static global method of loading the extra widgets on app startup.

    I am very happy to perform such a refactor and submit a pull request, but wanted to check if this was something you were interested in supporting @singerdmx before I committed too much time to this as it would be a breaking change.

    opened by Jon-Salmon 23
  • [WEB] Text is not displayed while typing - only when I change the browser window size (set state)

    [WEB] Text is not displayed while typing - only when I change the browser window size (set state)

    Hi there,

    first of all - a really great plugin!!

    Since version 0.3.1 Text is not displayed while typing on web - only when I change the browser window size (which I guess initiates a set state).

    This issue is also in the new 1.0.2 version

    web 
    opened by crossfire91 23
  • How to get only String to Display it in TextField ?

    How to get only String to Display it in TextField ?

    This is not an issue. Just a doubt. I just store data from quill editor as json in sqflite database and retrieve it, show it in Text widget. But what happens, it shows unknown characters when image or something stored in data. when extracted through toPlainText() method.

    So how to get only text which typed not any customizations. Thanks

    opened by c49is 22
  • Create the attributeBuilder method

    Create the attributeBuilder method

    Is it possible to create an attributeBuilder method that works just like embedBuilder? I have the code below, but I can't customize the view

    { "attributes": { "list": "checked" }, "insert": "\n" }, { "attributes": { "list": "unchecked" }, "insert": "\n" }

    opened by luscuissiatto 21
  • [Web], [Mobile], [Desktop] - Unable to insert link mailto and tel

    [Web], [Mobile], [Desktop] - Unable to insert link mailto and tel

    My issue is about all platforms.

    I have tried running example directory successfully before creating an issue here.

    When you want to add link - dialog with text and link input fields is opened. But, validation on the link field allows only http urls. It would be nice to have mailto and tel links also. In fact, in earlier versions of this lib this was possible.

    opened by tomotoshi3 0
  • [Mobile] Render URL image and URL video on text editor

    [Mobile] Render URL image and URL video on text editor

    My issue is about [Mobile]

    Is there any way to render image and video on text editor? So I can see the preview. I have tried to convert image/video to delta format and HTML format but the editor still didn't show the image/video.

    image image

    Expected : image image

    opened by alidinillah 0
  • [Mobile] Holding down backspace with external keyboard does not continuously delete

    [Mobile] Holding down backspace with external keyboard does not continuously delete

    I never noticed it before, but using built in iOS/Android keyboard you can hold down backspace and you will delete continuously, however with an external keyboard (or using keyboard on an iOS simulator) will only delete a single character if you hold backspace.

    My wrist is starting to hurt :)

    opened by mark8044 0
  • [Mobile] issue with links when you enter a url and then try to give it a human readable label while using LinkStyleButton

    [Mobile] issue with links when you enter a url and then try to give it a human readable label while using LinkStyleButton

    the following video will demonstrate how to reproduce this issue i am using flutter version 3.3.4 on stable channel, and using the example app on flutter_quill version 6.1.11 at the time of recording, the recording from an iOS simulator this can happen in a real device android/iOS

    https://user-images.githubusercontent.com/56353593/210167855-31e23160-9123-451a-bcb4-6da475aa2ddf.mov

    and this is this is the exception i receive

    
    ======== Exception caught by rendering library =====================================================
    The following assertion was thrown during paint():
    The provided text position is not in the current node
    'package:flutter_quill/src/widgets/text_line.dart':
    Failed assertion: line 1157 pos 12: 'container.containsOffset(position.offset)'
    
    The relevant error-causing widget was: 
      QuillEditor QuillEditor:file:///Users/myMac/Downloads/flutter-quill-master/example/lib/pages/home_page.dart:164:14
    When the exception was thrown, this was the stack: 
    #2      RenderEditableTextLine.globalToLocalPosition (package:flutter_quill/src/widgets/text_line.dart:1157:12)
    #3      RenderEditor._getOffsetForCaret (package:flutter_quill/src/widgets/editor.dart:870:33)
    #4      RenderEditor._updateSelectionExtentsVisibility (package:flutter_quill/src/widgets/editor.dart:860:23)
    #5      RenderEditor.paint (package:flutter_quill/src/widgets/editor.dart:1257:5)
    #6      RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2796:7)
    #7      PaintingContext.paintChild (package:flutter/src/rendering/object.dart:239:13)
    #8      RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:144:15)
    #9      PaintingContext.pushLayer (package:flutter/src/rendering/object.dart:460:12)
    #10     RenderLeaderLayer.paint (package:flutter/src/rendering/proxy_box.dart:4736:13)
    #11     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2796:7)
    #12     PaintingContext.paintChild (package:flutter/src/rendering/object.dart:239:13)
    #13     _RenderSingleChildViewport.paint.paintContents (package:flutter_quill/src/widgets/quill_single_child_scroll_view.dart:239:17)
    #14     PaintingContext.pushLayer (package:flutter/src/rendering/object.dart:460:12)
    #15     PaintingContext.pushClipRect (package:flutter/src/rendering/object.dart:520:7)
    #16     _RenderSingleChildViewport.paint (package:flutter_quill/src/widgets/quill_single_child_scroll_view.dart:243:40)
    #17     RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2796:7)
    #18     PaintingContext._repaintCompositedChild (package:flutter/src/rendering/object.dart:155:11)
    #19     PaintingContext.repaintCompositedChild (package:flutter/src/rendering/object.dart:98:5)
    #20     PipelineOwner.flushPaint (package:flutter/src/rendering/object.dart:1116:31)
    #21     RendererBinding.drawFrame (package:flutter/src/rendering/binding.dart:515:19)
    #22     WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:884:13)
    #23     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:378:5)
    #24     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1175:15)
    #25     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1104:9)
    #26     SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:1015:5)
    #27     _invoke (dart:ui/hooks.dart:148:13)
    #28     PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:318:5)
    #29     _drawFrame (dart:ui/hooks.dart:115:31)
    (elided 2 frames from class _AssertionError)
    The following RenderObject was being processed when the exception was fired: RenderEditor#fb57c relayoutBoundary=up19
    ...  needs compositing
    ...  parentData: <none> (can use size)
    ...  constraints: BoxConstraints(0.0<=w<=398.0, 0.0<=h<=Infinity)
    ...  size: Size(398.0, 21.0)
    RenderObject: RenderEditor#fb57c relayoutBoundary=up19
      needs compositing
      parentData: <none> (can use size)
      constraints: BoxConstraints(0.0<=w<=398.0, 0.0<=h<=Infinity)
      size: Size(398.0, 21.0)
    ...  child 1: RenderEditableTextLine#5b3b6 relayoutBoundary=up20
    ...    needs compositing
    ...    parentData: offset=Offset(0.0, 0.0) (can use size)
    ...    constraints: BoxConstraints(w=398.0, 0.0<=h<=Infinity)
    ...    layer: OffsetLayer#d05b0
    ...      engine layer: OffsetEngineLayer#5bda1
    ...      handles: 2
    ...      offset: Offset(0.0, 0.0)
    ...    size: Size(398.0, 21.0)
    ...    body: RenderParagraphProxy#f9e48 relayoutBoundary=up21
    ...      parentData: offset=Offset(0.0, 0.0) (can use size)
    ...      constraints: BoxConstraints(w=398.0, 0.0<=h<=Infinity)
    ...      size: Size(398.0, 21.0)
    ...      child: RenderParagraph#e0697 relayoutBoundary=up22
    ...        parentData: <none> (can use size)
    ...        constraints: BoxConstraints(w=398.0, 0.0<=h<=Infinity)
    ...        semantic boundary
    ...        size: Size(398.0, 21.0)
    ...        textAlign: start
    ...        textDirection: ltr
    ...        softWrap: wrapping at box width
    ...        overflow: clip
    ...        locale: en_US
    ...        maxLines: unlimited
    ...        text: TextSpan
    ...          debugLabel: ((englishLike bodyMedium 2014).merge(blackCupertino bodyMedium)).copyWith
    ...          inherit: false
    ...          color: Color(0xdd000000)
    ...          family: .SF UI Text
    ...          size: 16.0
    ...          weight: 400
    ...          baseline: alphabetic
    ...          height: 1.3x
    ...          decoration: TextDecoration.none
    ====================================================================================================
    
    
    opened by mwothman 0
Owner
X Code
If you are interested in Java, Spring Boot or React, have a look 1o24bbs.com/t/24180
X Code
An Instagram like text editor Flutter widget that helps you to change your text style.

TextEditor An instagram like text editor widget for flutter Show some ❤️ and star the repo to support the project Features Edit TextStyle object font

Mehdi Zarepour 68 Dec 16, 2022
WYSIWYG editor for Flutter with a rich set of supported formatting options. (WIP)

✨ rich_editor WYSIWYG editor for Flutter with a rich set of supported formatting options. Based on https://github.com/dankito/RichTextEditor, but for

Festus Olusegun 116 Dec 27, 2022
DeerNote is a solution for cross-platform rich editor

#DeerNote is a solution for cross-platform rich editor ###DeerNote contains parts as follows: db: mongodb server: nodejs app: flutter launch mongdb se

null 3 Dec 6, 2022
Json editor - A json editor on flutter

Features Support add comment; Support show errors for invalid json text; Pretty

Chan Young 12 Nov 18, 2022
Masked text field - A flutter package for masked text field for formet your text and good UI

Masked Text Field Masked Text Field Features A package for masked text field for

Alok Dubey 7 Sep 4, 2022
Text analyzer that extracts tokens from text for use in full-text search queries and indexes.

Tokenize text, compute document readbility and compare terms in Natural Language Processing. THIS PACKAGE IS PRE-RELEASE, and SUBJECT TO DAILY BREAKIN

GM Consult Pty Ltd 5 Dec 12, 2022
Soft and gentle rich text editing for Flutter applications.

About Fleather Soft and gentle rich text editing for Flutter applications based on Zefyr. Clean and modern look Fleather's rich text editor is built w

Fleather 25 Dec 24, 2022
📝 Simple text editor/notepad with cloud sync.

txt Simple text editor/notepad with cloud sync. Build Install dependencies: flutter pub get Build: flutter build apk, flutter build ios etc. ToDo's Ad

Crazy Marvin 35 Jan 1, 2023
Grad text package - A Flutter Widget to draw gradients into text

grad_text A Flutter Widget to draw gradients into text.(Null safe) Demo Install

Karthik Sunil K 3 Jan 31, 2022
Detectable text field - Flutter Text widgets with detection features

detectable_text_field Text widgets with detection features. You can detect hasht

null 0 Feb 2, 2022
A text field that displays text on different languages based on your selection.

translatable_text_field A text field that displays text on different languages based on your selection. Its basic idea is that you place this fields i

null 0 Mar 13, 2022
A cross-platform flutter package to convert your links into rich beautiful previews.

Link Preview Generator A cross-platform flutter package to convert your links into rich beautiful previews. This package is inspired from Any Link Pre

Pranav Bedre 12 Oct 21, 2022
Rules - Powerful and feature-rich validation library for both Dart and Flutter.

Introduction Rules - Powerful and feature-rich validation library for both Dart and Flutter. Rules is a simple yet powerful and feature-rich validatio

Ganesh Rathinavel 24 Dec 12, 2022
A Flutter application for viewing a rich feed of GitHub activity.

github_activity_feed A Flutter application for viewing a rich feed of GitHub activity. Project status: Public Preview: Version 0.8.2 Supported platfor

Reuben Turner 74 Nov 24, 2022
A rich, convenient, easy-to-use flutter page transition package

flutter_page_transition A rich, convenient, easy-to-use flutter page transition package. README in Chinese Some Demos Getting Started Add this to your

Double Han 56 Sep 27, 2022
Planets An example for a rich ui on Flutter

planets An example for a rich ui on Flutter Origin I saw a nice UI example in UpLabs.com (https://www.uplabs.com/posts/space-travel-ui) and I decided

Carlos Drudi - MySafety 2 Apr 5, 2021
Rich UI and animation flutter app backed by firebase

firebasecrud Guardians of tech A new Flutter application. Getting Started Note: Add project to firebase This project is a starting point for a Flutter

Divyam joshi 123 Nov 28, 2022
A flutter app that gives you affirmation you daily need by saying "I am Freaking rich!"

A very basic flutter app that gives you affirmation you daily need by saying "I am Freaking rich!" ?? What’s In This Document Get Up and Running in 5

Bhavuk kalra 1 Feb 15, 2022
Just a simple interface showing a diamond, an imitation to that old application called I am rich .

i_am_rich A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started if thi

Nixi 0 Dec 29, 2021