{"id":16647501,"url":"https://github.com/cathood0/flutter_quill_delta_easy_parser","last_synced_at":"2025-09-05T12:33:31.424Z","repository":{"id":248990657,"uuid":"830283953","full_name":"CatHood0/flutter_quill_delta_easy_parser","owner":"CatHood0","description":"Convert your Quill Delta into a simplified document format, making it easier to manage and manipulate text attributes","archived":false,"fork":false,"pushed_at":"2025-02-28T04:18:04.000Z","size":58,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"Main","last_synced_at":"2025-02-28T11:51:42.473Z","etag":null,"topics":["delta","document","flutter-quill","parser","quill-delta","rich-text"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/flutter_quill_delta_easy_parser","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CatHood0.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-07-18T01:30:05.000Z","updated_at":"2025-02-28T04:17:00.000Z","dependencies_parsed_at":"2024-07-18T09:53:10.250Z","dependency_job_id":"e44bbdee-30b9-4be9-b28d-6a95aa0efaa0","html_url":"https://github.com/CatHood0/flutter_quill_delta_easy_parser","commit_stats":null,"previous_names":["cathood0/flutter_quill_delta_easy_parser"],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CatHood0%2Fflutter_quill_delta_easy_parser","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CatHood0%2Fflutter_quill_delta_easy_parser/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CatHood0%2Fflutter_quill_delta_easy_parser/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CatHood0%2Fflutter_quill_delta_easy_parser/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CatHood0","download_url":"https://codeload.github.com/CatHood0/flutter_quill_delta_easy_parser/tar.gz/refs/heads/Main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243204111,"owners_count":20253413,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["delta","document","flutter-quill","parser","quill-delta","rich-text"],"created_at":"2024-10-12T08:44:58.247Z","updated_at":"2025-09-05T12:33:31.403Z","avatar_url":"https://github.com/CatHood0.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Flutter Quill Easy Parser\n\nA Flutter package designed to transform `Flutter Quill` content into a structured document format, making it easier to handle and convert for various use cases like generating `Word` or `PDF` documents.\n\n\u003e [!TIP]\n\u003e\n\u003e If you're using version 1.0.6 or minor versions, see [the migration guide to migrate to 1.1.3](https://github.com/CatHood0/flutter_quill_delta_easy_parser/blob/Main/doc/v106_to_v113.md).\n\n## Usage Example\n\n```dart\nimport 'package:flutter_quill_delta_easy_parser/flutter_quill_delta_easy_parser.dart';\n\nvoid main() {\n  final delta = Delta()\n    ..insert('This is ')\n    ..insert('bold', {'bold': true})\n    ..insert(' and ')\n    ..insert('italic', {'italic': true})\n    ..insert(' text with ')\n    ..insert('custom color', {'color': '#FF0000'})\n    ..insert('\\n\\n', {'header': 1})\n    ..insert('This is a list item')\n    ..insert('\\n', {'list': 'ordered'})\n    ..insert('Another list item')\n    ..insert('\\n', {'list': 'ordered'})\n    ..insert('Third list item')\n    ..insert('\\n')\n    ..insert('This is a ')\n    ..insert('link', {'link': 'https://example.com'})\n    ..insert(' to a website')\n    ..insert('\\n');\n\nfinal Document? document = DocumentParser()\n    .parseDelta(\n      delta: delta,\n      returnNoSealedCopies: false,\n      ignoreAllNewLines: false,\n    );\ndebugPrint(document.toPrettyString());\n}\n```\n\n**Output in console**:\n\n```console\nDocument:\n    Paragraph:\n        Line: [\n          TextFragment: \"This is \"\n          TextFragment: \"bold\", Attributes: {bold: true}\n          TextFragment: \" and \"\n          TextFragment: \"italic\", Attributes: {italic: true}\n          TextFragment: \" text with \"\n          TextFragment: \"custom color\", Attributes: {color: #FF0000}\n        ]\n        Paragraph Attributes: {header: 1}\n        Type: block \n    Paragraph:\n        Line: [\n          TextFragment: \"\\n\"\n        ]\n        Paragraph Attributes: {header: 1}\n        Type: lineBreak \n    Paragraph:\n        Line: [\n          TextFragment: \"This is a list item\"\n        ]\n        Line: [\n          TextFragment: \"Another list item\"\n        ]\n        Paragraph Attributes: {list: ordered}\n        Type: block \n    Paragraph:\n        Line: [\n          TextFragment: \"Third list item\",\n        ]\n        Line: [\n          TextFragment: \"This is a \"\n          TextFragment: \"link\", Attributes: {link: https://example.com}\n          TextFragment: \" to a website\"\n        ]\n        Type: inline \n```\n\n## What Does `DocumentParser`?\n\nTransforms the content of a **Quill JS** editor and **Flutter Quill** editors into an easy-to-work paragraph format.\n\nThe output of both editors is `Delta` format. While the `Delta` format works great, but, when you need to use it to generate other types of documents (e.g., Word or PDF) from Quill's contents, you probably will need to do more work to format the paragraphs correctly without losses the styles.\n\n## Easy example usage\n\n```dart\nimport 'package:flutter_quill_delta_easy_parser/flutter_quill_delta_easy_parser.dart';\n\nfinal Delta delta = Delta()\n  ..insert('Hello, how are you? ')\n  ..insert('The first Major Section')\n  ..insert('\\n', {'header': 1})\n  ..insert('We are writing some ')\n  ..insert('bolded text',{'bold': true})\n  ..insert('\\n');\nfinal Document? parsedDocument = DocumentParser(mergerBuilder: const CommonMergerBuilder()).parseDelta(delta: delta);\n/* \nit's equal, to build a document manually like this:\nfinal Document document = Document(paragraphs: [\n  Paragraph(\n    lines: [\n      Line(fragments: [\n        TextFragment(data: \"Hello, how are you? The first Major Section\"),\n      ]),\n    ],\n    blockAttributes: {\"header\": 1},\n    type: ParagraphType.block,\n  ),\n  Paragraph(\n    lines: [\n      Line(fragments: [\n        TextFragment(data: \"We are writing some \"),\n        TextFragment(data: \"bolded text\", attributes: {\"bold\": true})\n      ]),\n    ],\n    type: ParagraphType.inline,\n  ),\n  Paragraph.newLine(),\n]);\n*/\n```\n\n## MergerBuilder\n\n`MergerBuilder` is an abstract class that allows us to implement our own logic to join different paragraphs. By default, `DocumentParser` implements `CommonMergerBuilder`, which focuses on joining paragraphs that maintain the same types, or the same block-attributes.\n\nCurrently, only **3** implementations are available:\n\n* `NoMergerBuilder`: does not execute any code and returns the paragraphs as they are created.\n* `BlockMergerBuilder`: joins all paragraphs that contain the same block-attributes (in a row, from the first to the last, not randomly).\n* `CommonMergerBuilder` (we already described it above).\n\n```dart\nfinal parser = DocumentParser(mergerBuilder: \u003cthe-merger-that-you-want\u003e);\n```\n\n## About the `Paragraph`, `Line` and `TextFragment` API\n\n### The Paragraph Format\n\nThe `Paragraph` format is a simple format, where an object contains a list of lines, these \"lines\" are completely separated from the others. The value contained in `blockAttributes` must be applied to all lines, regardless.\n\nEach `Paragraph`, depending on its content and attributes, can have a different type. For example:\n\n* A `Paragraph` whose content is a `Line` that has an object totally different from a string, will be considered as a `ParagraphType.embed`.\n* A `Paragraph`, whose content is pure strings, but that contains `blockAttributes`, will be considered a `ParagraphType.block`.\n* A `Paragraph`, whose content only has one new-line, will be considered a `ParagraphType.lineBreak` (even if this new line is applied some type of `blockAttribute`).\n\n\u003e [!NOTE] \n\u003e The only reason why a `Paragraph` should contain several lines at the same time, is because these lines share the same **block-attributes** (which may or may not have it).\n\n\n`Paragraph` looks like:\n\n```dart\nclass Paragraph {\n  final String id;\n  // this is an enum that contains values like: inline, block, lineBreak and embed\n  ParagraphType type;\n  // contains all attributes (usually block attributes like \"header\", \"align\" or \"code-block\") \n  //that will be applied to whole lines\n  Map\u003cString, dynamic\u003e? blockAttributes; \n\n  // Determines if this instance can be modified \n  //\n  // false by default to allow any type of modification\n  bool _seal;\n  final List\u003cLine\u003e _lines;\n\n  Paragraph({\n    required this.lines,\n    required this.type,\n    this.blockAttributes,\n    String? id,\n  });\n}\n```\n\n### Line\n\n`Line` class represents a section of the `paragraph` separates of its siblings. \n\n```dart\nclass Line {\n  final String id;\n  final List\u003cTextFragment\u003e _fragments;\n  // if the line is sealed, then we cannot \n  // add/remove/update any fragment into it\n  bool _sealed;\n\n  Line({\n    required List\u003cTextFragment\u003e fragments,\n    String? id,\n  });\n\n  // General methods\n  List\u003cTextFragment\u003e get fragments;\n  void removeFragment(TextFragment fragment);\n  void addFragment(TextFragment fragment);\n  void updateFragment(int index, TextFragment fragment);\n}\n```\n\nThis is useful when we have a **list**, **code-block** or **blockquote**, because every \"`Line`\" represents another item an allow us create them without make a manual accumulation. By default, all of them are merged using `mergerBuilder` and passing `CommonMergerBuilder` in `DocumentParser`, but, if you want to avoid merge any `Paragraph` with its similar parts, then just use `NoMergerBuilder`. \n\nYou can see now it, like this plain text diagram representation:\n```\n┌─────────────Paragraph─────────────────┐\n│ 1. This is a ordered list item        │\n│ 2. This is another ordered list item  │\n│ 3. Just a different ordered list item │\n└───────────────────────────────────────┘\n```\n\nIts similar to create a `Paragraph` like (just when `BlockMergerBuilder` or `CommonMergerBuilder` is being used):\n\n```dart\nParagraph(\n lines: [\n   Line(fragments: [\n     TextFragment(data: 'This is a ordered list item')\n   ]),\n   Line(fragments: [\n     TextFragment(data: 'This is another ordered list item'),\n   ]),\n   Line(fragments: [\n     TextFragment(data: 'Just a different ordered list item'),\n   ]),\n ],\n blockAttributes: {'list': 'ordered'},\n type: ParagraphType.block,\n);\n```\n\n### TextFragment\n\nA `TextFragment` represents a segment of content within a `Paragraph`. This content can be a simple String of characters or a more complex structure such as an embed.\n\n```dart\nclass TextFragment{\n  Object data;\n  Map\u003cString, dynamic\u003e? attributes;\n\n  TextFragment({\n    required this.data,\n    this.attributes,\n  });\n}\n```\n\n### Paragraph with lines example:\n\n```dart\nfinal Paragraph basicParagraph = Paragraph(\n  lines: [\n    Line(fragments: [\n      TextFragment(data: 'I am building a new package in Dart. '),\n      TextFragment(data: 'This package will be ', attributes: {'bold': true}),\n      TextFragment(data: 'open source', attributes: {'italic': true}),\n      TextFragment(data: ' and it will help developers process the text entered into a QuillJS editor.'),\n    ]),\n  ],\n  type: ParagraphType.inline,\n);\n// another factory constructors\nfinal Paragraph embedPr = Paragraph.fromRawEmbed(data: {'image': 'https://example.com/image.png'}, attributes: null, blockAttributes: null); \nfinal Paragraph embedPrWithOp = Paragraph.fromEmbed(data: Operation.insert({'image': 'https://example.com/image.png'})); \nfinal Paragraph newLinePr = Paragraph.newLine(blockAttributes: null); \n// A `Paragraph` can also have a `blockAttributes` property. This property indicates what type of paragraph-level formatting has \n//  been applied. For instance, a header is a `Paragraph` that is formatted as a header. \n// Similarly, a bullet point is a `Paragraph` that is formatted as a bullet point. \n//\n// Example:\nfinal Paragraph bulletListParagraph = Paragraph.auto(\n  lines: [Line(fragments: [\n      TextFragment(data: \"I am also a bullet point, but I have \"),\n      TextFragment(data: \"underlined text\", attributes: {\"underline\": true}),\n      TextFragment(data: \" included in my paragraph.\"),\n    ]),\n  ],\n  blockAttributes: {\"list\": \"bullet\"},\n);\n\ndebugPrint(bulletListParagraph.type.name); // output: block \n```\n\nSee the test folder for detailed usage examples and test cases.\n\n## License\n\nThis project is licensed under the BSD-3-Clause License - see the [LICENSE](https://github.com/CatHood0/flutter_quill_delta_easy_parser/blob/Main/LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcathood0%2Fflutter_quill_delta_easy_parser","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcathood0%2Fflutter_quill_delta_easy_parser","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcathood0%2Fflutter_quill_delta_easy_parser/lists"}