Html conventor package

pull/1523/head
Ellet 1 year ago
parent 78e48eb49b
commit b07b26326b
No known key found for this signature in database
GPG Key ID: C488CC70BBCEF0D1
  1. 34
      example/lib/pages/home_page.dart
  2. 6
      example/pubspec.yaml
  3. 8
      packages/README.md
  4. 30
      packages/flutter_quill_html/.gitignore
  5. 10
      packages/flutter_quill_html/.metadata
  6. 3
      packages/flutter_quill_html/CHANGELOG.md
  7. 1
      packages/flutter_quill_html/LICENSE
  8. 23
      packages/flutter_quill_html/README.md
  9. 36
      packages/flutter_quill_html/analysis_options.yaml
  10. 1
      packages/flutter_quill_html/delta_markdown
  11. 132
      packages/flutter_quill_html/lib/flutter_quill_html.dart
  12. 38
      packages/flutter_quill_html/pubspec.yaml
  13. 3
      packages/flutter_quill_html/pubspec_overrides.yaml.g
  14. 7
      packages/flutter_quill_html/test/flutter_quill_html_test.dart
  15. 5
      scripts/disable_local_dev.sh
  16. 5
      scripts/enable_local_dev.sh

@ -15,6 +15,7 @@ import 'package:flutter_quill/flutter_quill.dart';
import 'package:flutter_quill_extensions/flutter_quill_extensions.dart'; import 'package:flutter_quill_extensions/flutter_quill_extensions.dart';
import 'package:flutter_quill_extensions/logic/services/image_picker/image_picker.dart'; import 'package:flutter_quill_extensions/logic/services/image_picker/image_picker.dart';
import 'package:flutter_quill_extensions/presentation/embeds/widgets/image.dart'; import 'package:flutter_quill_extensions/presentation/embeds/widgets/image.dart';
import 'package:flutter_quill_html/flutter_quill_html.dart';
import 'package:image_cropper/image_cropper.dart'; import 'package:image_cropper/image_cropper.dart';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
@ -120,10 +121,12 @@ class _HomePageState extends State<HomePage> {
), ),
), ),
IconButton( IconButton(
onPressed: () => _insertTimeStamp( onPressed: () {
_controller, _insertTimeStamp(
DateTime.now().toString(), _controller,
), DateTime.now().toString(),
);
},
icon: const Icon(Icons.add_alarm_rounded), icon: const Icon(Icons.add_alarm_rounded),
), ),
IconButton( IconButton(
@ -264,6 +267,29 @@ class _HomePageState extends State<HomePage> {
} }
}, },
), ),
ListTile(
title: const Text('Convert to/from HTML'),
onTap: () async {
final scaffoldMessenger = ScaffoldMessenger.of(context);
final navigator = Navigator.of(context);
try {
final html = _controller.document.toDelta().toHtml();
print(html);
_controller.document =
Document.fromDelta(DeltaHtmlExt.fromHtml(html));
} catch (e) {
scaffoldMessenger.showSnackBar(
SnackBar(
content: Text(
'Error while convert to/from HTML: ${e.toString()}',
),
),
);
} finally {
navigator.pop();
}
},
),
_buildMenuBar(context), _buildMenuBar(context),
], ],
), ),

@ -17,8 +17,10 @@ dependencies:
path_provider: ^2.1.1 path_provider: ^2.1.1
# filesystem_picker: ^4.0.0 # filesystem_picker: ^4.0.0
file_picker: ^6.1.1 file_picker: ^6.1.1
flutter_quill: ^8.4.1 flutter_quill: ^8.5.1
flutter_quill_extensions: ^0.6.5 flutter_quill_extensions: ^0.6.7
flutter_quill_html:
path: ../packages/flutter_quill_html
path: ^1.8.3 path: ^1.8.3
desktop_drop: ^0.4.4 desktop_drop: ^0.4.4
image_cropper: ^5.0.0 image_cropper: ^5.0.0

@ -3,4 +3,10 @@
This folder contains packages that add more features to the [FlutterQuill](../README.md) This folder contains packages that add more features to the [FlutterQuill](../README.md)
that might be outside of the packages main purpose that might be outside of the packages main purpose
This page will be updated soon. ## Table of contents
- [Flutter Quill Packages](#flutter-quill-packages)
- [Table of contents](#table-of-contents)
- [Packages](#packages)
## Packages
- [flutter_quill_html](./flutter_quill_html/)

@ -0,0 +1,30 @@
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
migrate_working_dir/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
/pubspec.lock
**/doc/api/
.dart_tool/
.packages
build/

@ -0,0 +1,10 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: "d211f42860350d914a5ad8102f9ec32764dc6d06"
channel: "stable"
project_type: package

@ -0,0 +1,3 @@
## 0.0.1
* TODO: Describe initial release.

@ -0,0 +1 @@
TODO: Add your license here.

@ -0,0 +1,23 @@
# Flutter Quill HTML
A extension for [flutter_quill](https://pub.dev/packages/flutter_quill) package to add support for dealing with conversion to/from html
It uses [vsc_quill_delta_to_html](https://pub.dev/packages/vsc_quill_delta_to_html) package to convert the the delta to HTML
## Features
```markdown
- Easy to use
- Support with Flutter Quill package
```
## Getting started
This will be updated soon.
## Usage
Take a look at the example of the repo, This will be updated soon.
## Additional information
This will be updated soon.

@ -0,0 +1,36 @@
include: package:flutter_lints/flutter.yaml
analyzer:
errors:
undefined_prefixed_name: ignore
unsafe_html: ignore
linter:
rules:
always_declare_return_types: true
always_put_required_named_parameters_first: true
annotate_overrides: true
avoid_empty_else: true
avoid_escaping_inner_quotes: true
avoid_print: true
avoid_redundant_argument_values: true
avoid_types_on_closure_parameters: true
avoid_void_async: true
cascade_invocations: true
directives_ordering: true
omit_local_variable_types: true
prefer_const_constructors: true
prefer_const_constructors_in_immutables: true
prefer_const_declarations: true
prefer_final_fields: true
prefer_final_in_for_each: true
prefer_final_locals: true
prefer_initializing_formals: true
prefer_int_literals: true
prefer_interpolation_to_compose_strings: true
prefer_relative_imports: true
prefer_single_quotes: true
sort_constructors_first: true
sort_unnamed_constructors_first: true
unnecessary_lambdas: true
unnecessary_parenthesis: true
unnecessary_string_interpolations: true

@ -0,0 +1 @@
Subproject commit 22e49a1abe72894f6666baedcc00fb89f13d2c4a

@ -0,0 +1,132 @@
library flutter_quill_html;
import 'dart:convert' show jsonDecode;
import 'package:delta_markdown/delta_markdown.dart' show markdownToDelta;
import 'package:flutter/foundation.dart';
import 'package:flutter_quill/flutter_quill.dart' show Delta;
// ignore: depend_on_referenced_packages
import 'package:html/dom.dart' as html_dom;
// ignore: depend_on_referenced_packages
import 'package:html/parser.dart' as html_parse;
import 'package:html2md/html2md.dart' as html2md;
import 'package:vsc_quill_delta_to_html/vsc_quill_delta_to_html.dart'
as conventer show ConverterOptions, QuillDeltaToHtmlConverter;
typedef ConverterOptions = conventer.ConverterOptions;
extension DeltaHtmlExt on Delta {
String toHtml({ConverterOptions? options}) {
final html = conventer.QuillDeltaToHtmlConverter(
List.castFrom(toJson()),
options,
).convert();
return html;
}
static Delta fromHtml(String html) {
return Delta.fromJson(
jsonDecode(
markdownToDelta(
html2md.convert(html),
),
),
);
}
}
// From https://github.com/singerdmx/flutter-quill/issues/1100#issuecomment-1681274676
@immutable
class HtmlToDeltaConverter {
static const _collorPattern = r'color: rgb\((\d+), (\d+), (\d+)\);';
static Delta _parseInlineStyles(html_dom.Element element) {
var delta = Delta();
for (final node in element.nodes) {
final attributes = _parseElementStyles(element);
if (node is html_dom.Text) {
delta.insert(node.text, attributes);
} else if (node is html_dom.Element && node.localName == 'img') {
final src = node.attributes['src'];
if (src != null) {
delta.insert({'image': src});
}
} else if (node is html_dom.Element) {
delta = delta.concat(_parseInlineStyles(node));
}
}
return delta;
}
static Map<String, dynamic> _parseElementStyles(html_dom.Element element) {
final attributes = <String, dynamic>{};
if (element.localName == 'strong') attributes['bold'] = true;
if (element.localName == 'em') attributes['italic'] = true;
if (element.localName == 'u') attributes['underline'] = true;
if (element.localName == 'del') attributes['strike'] = true;
final style = element.attributes['style'];
if (style != null) {
final colorValue = _parseColorFromStyle(style);
if (colorValue != null) attributes['color'] = colorValue;
final bgColorValue = _parseBackgroundColorFromStyle(style);
if (bgColorValue != null) attributes['background'] = bgColorValue;
}
return attributes;
}
static String? _parseColorFromStyle(String style) {
if (RegExp(r'(^|\s)color:(\s|$)').hasMatch(style)) {
return _parseRgbColorFromMatch(RegExp(_collorPattern).firstMatch(style));
}
return null;
}
static String? _parseBackgroundColorFromStyle(String style) {
if (RegExp(r'(^|\s)background-color:(\s|$)').hasMatch(style)) {
return _parseRgbColorFromMatch(RegExp(_collorPattern).firstMatch(style));
}
return null;
}
static String? _parseRgbColorFromMatch(RegExpMatch? colorMatch) {
if (colorMatch != null) {
try {
final red = int.parse(colorMatch.group(1)!);
final green = int.parse(colorMatch.group(2)!);
final blue = int.parse(colorMatch.group(3)!);
return '#${red.toRadixString(16).padLeft(2, '0')}${green.toRadixString(16).padLeft(2, '0')}${blue.toRadixString(16).padLeft(2, '0')}';
} catch (e) {
// debugPrintStack(label: e.toString());
}
}
return null;
}
static Delta htmlToDelta(String html) {
final document = html_parse.parse(html);
var delta = Delta();
for (final node in document.body?.nodes ?? []) {
if (node is html_dom.Element) {
switch (node.localName) {
case 'p':
delta = delta.concat(_parseInlineStyles(node))..insert('\n');
break;
case 'br':
delta.insert('\n');
break;
}
}
}
return html.isNotEmpty ? delta : Delta()
..insert('\n');
}
}

@ -0,0 +1,38 @@
name: flutter_quill_html
description: A extension for flutter_quill package to add support for dealing with conversion to/from html
version: 0.0.1-experimental.1
homepage: https://github.com/singerdmx/flutter-quill/tree/master/packages/flutter_quill_html
repository: https://github.com/singerdmx/flutter-quill/tree/master/packages/flutter_quill_html
topics:
- ui
- widgets
- widget
- rich-text-editor
- quill
environment:
sdk: '>=3.1.5 <4.0.0'
flutter: ">=1.17.0"
dependencies:
flutter:
sdk: flutter
flutter_quill: ^8.5.1
vsc_quill_delta_to_html: ^1.0.3
html2md: ^1.3.1
delta_markdown:
path: ./delta_markdown
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^3.0.1
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
# The following section is specific to Flutter packages.
flutter:
uses-material-design: true

@ -0,0 +1,3 @@
dependency_overrides:
flutter_quill:
path: ../../

@ -0,0 +1,7 @@
import 'package:flutter_test/flutter_test.dart';
void main() {
test('No tests for now', () {
expect(true, true);
});
}

@ -19,4 +19,9 @@ rm flutter_quill_test/pubspec_overrides.yaml
echo "" echo ""
echo "Disable local development for all the other packages..."
rm packages/flutter_quill_html/pubspec_overrides.yaml
echo ""
echo "Local development for all libraries has been disabled, please 'flutter pub get' for each one of them" echo "Local development for all libraries has been disabled, please 'flutter pub get' for each one of them"

@ -19,4 +19,9 @@ cp flutter_quill_test/pubspec_overrides.yaml.g flutter_quill_test/pubspec_overri
echo "" echo ""
echo "Enable local development for all the other packages..."
cp packages/flutter_quill_html/pubspec_overrides.yaml.g packages/flutter_quill_html/pubspec_overrides.yaml
echo ""
echo "Local development for all libraries has been enabled, please 'flutter pub get' for each one of them" echo "Local development for all libraries has been enabled, please 'flutter pub get' for each one of them"
Loading…
Cancel
Save