library quill_html_converter; import 'package:dart_quill_delta/dart_quill_delta.dart'; import 'package:vsc_quill_delta_to_html/vsc_quill_delta_to_html.dart' as converter show ConverterOptions, QuillDeltaToHtmlConverter, OpAttributeSanitizerOptions, OpConverterOptions, InlineStyles, InlineStyleType, defaultInlineFonts; typedef ConverterOptions = converter.ConverterOptions; /// A extension for [Delta] which comes from `flutter_quill` to extends /// the functionality of it to support converting the [Delta] to/from HTML extension DeltaHtmlExt on Delta { /// Convert the [Delta] instance to HTML Raw string /// /// It will run using the following steps: /// /// 1. Convert the [Delta] to json using [toJson] /// 2. Cast the json map as `List>` /// 3. Pass it to the conventer `vsc_quill_delta_to_html` which is a package /// that designed specifically for converting the quill delta to html String toHtml({ConverterOptions? options}) { final json = toJson(); final html = converter.QuillDeltaToHtmlConverter( List.castFrom(json), options ?? _defaultConverterOptions, ).convert(); return html; } } /// Configuration options for converting Quill Delta to HTML. /// This includes various settings for how different elements and styles should be handled. final _defaultConverterOptions = ConverterOptions( // Tag to be used for ordered lists orderedListTag: 'ol', // Tag to be used for bullet lists bulletListTag: 'ul', // Enable multi-line blockquote conversion multiLineBlockquote: true, // Enable multi-line header conversion multiLineHeader: true, // Enable multi-line code block conversion multiLineCodeblock: true, // Enable multi-line paragraph conversion multiLineParagraph: true, // Enable multi-line custom block conversion multiLineCustomBlock: true, // Options for sanitizing attributes sanitizerOptions: converter.OpAttributeSanitizerOptions( // Allow 8-digit hex colors in styles allow8DigitHexColors: true, ), // This handle specific styles and attributes converterOptions: converter.OpConverterOptions( customCssStyles: (op) { // Validate if our attributes exist in [DeltaInsertOp] // and return the necessary HTML style // These lists of attributes, are passed as inline styles // // For example, if you have a delta like -> // [ { "insert": "hello", "attributes": { "line-height": 1.5 }} ] // // Without the validation below to verify if exist line-height atribute in the Operation, it would be: //

hello

-> isn't created the attribute // // But, with this validation an implementation of the style will be: //

hello

if (op.attributes['line-height'] != null) { return ['line-height: ${op.attributes['line-height']}px']; } if (op.isImage()) { // Fit images within restricted parent width return ['max-width: 100%', 'object-fit: contain']; } return null; }, // Enable inline styles inlineStylesFlag: true, inlineStyles: converter.InlineStyles( { 'font': converter.InlineStyleType( fn: (value, _) => converter.defaultInlineFonts[value] ?? 'font-family: $value', ), 'size': converter.InlineStyleType( fn: (value, _) { // Default sizes if (value == 'small') return 'font-size: 0.75em'; if (value == 'large') return 'font-size: 1.5em'; if (value == 'huge') return 'font-size: 2.5em'; // Accept any int or double type size return 'font-size: ${value}px'; }, ), 'indent': converter.InlineStyleType( fn: (value, op) { // Calculate indent size based on the value final indentSize = (double.tryParse(value) ?? double.nan) * 3; // Determine side for padding based on text direction final side = op.attributes['direction'] == 'rtl' ? 'right' : 'left'; return 'padding-$side:${indentSize}em'; }, ), 'list': converter.InlineStyleType( map: { // Styles for checked and unchecked list items 'checked': "list-style-type:'\\2611';padding-left: 0.5em;", 'unchecked': "list-style-type:'\\2610';padding-left: 0.5em;", }, ), }, ), ), );