memspace / zefyr

Soft and gentle rich text editing for Flutter applications.
https://zefyr-editor.gitbook.io
2.22k stars 551 forks source link

edit html with zefyr and notus #250

Open veneno261 opened 4 years ago

veneno261 commented 4 years ago

i use @nalbion solution and i can edit html with zefyr and export as html i get html from api convert it to markdown with html2md package then convert it to Delta with notusMarkdown.decode(markdown) and show it with NotusDocument.fromDelta its ok until your html contain heading or list and if your html contain those, this error throwing

The following assertion was thrown building Builder:
Style cannot be applied to this leaf node: {block: ul}
'package:notus/src/document/leaf.dart':
Failed assertion: line 106 pos 12: 'value != null && (value.isInline || value.isEmpty)'

what can i do ? anyone know another way or any solution to solve this problem ? thanks for your help

cgestes commented 4 years ago

It looks like the generated Delta from notusMarkdown.decode is incorrect.

Can you post the content of a faulty Delta, and of a working one (done using zefyr) so that we can compare and nail down the issue?

veneno261 commented 4 years ago

this is my editor page

import 'package:flutter/material.dart';
import 'package:notus/convert.dart';
import 'package:zefyr/zefyr.dart';
import 'package:html2md/html2md.dart' as html2md;

class EditorPage extends StatefulWidget {

  final String text;
  final Function setText;
  EditorPage({this.text, this.setText});

  @override
  EditorPageState createState() => EditorPageState();
}

class EditorPageState extends State<EditorPage> {

  ZefyrController _controller;
  FocusNode _focusNode;

  @override
  void initState() {
    super.initState();

    final document = _loadNotes();
    _controller = ZefyrController(document);
    _focusNode = FocusNode();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Editor"),
        actions: <Widget>[
          GestureDetector(
            onTap: () => _saveNotes(),
            child: Center(
              child: Padding(
                padding: const EdgeInsets.only(left: 15),
                child: Text('Save'),
              ),
            ),
          )
        ],
      ),
      body: ZefyrScaffold(
        child: ZefyrEditor(
          padding: EdgeInsets.all(16),
          controller: _controller,
          focusNode: _focusNode,
        ),
      ),
    );
  }

  NotusDocument _loadNotes() {
    var markdown = html2md.convert(widget.text);

    if (markdown == null || markdown == '') {
      return NotusDocument();
    }

    return NotusDocument.fromDelta(notusMarkdown.decode(markdown));
  }

  _saveNotes() {
    final html = notusHTML.encode(_controller.document.toDelta());
    widget.setText('<p>' + html + '</p>');
    Navigator.of(context).pop();
  }
}

this is zefyr document output

I/flutter ( 2915): ¶ ⟨hello⟩b ⏎
I/flutter ( 2915): ¶ ⟨this is list⟩ ⏎ {heading: 2}
I/flutter ( 2915): ¶  ⏎
I/flutter ( 2915): § {ul}
I/flutter ( 2915):   ├ ¶ ⟨item 1⟩ ⏎ {block: ul}
I/flutter ( 2915):   ├ ¶ ⟨item 2⟩ ⏎ {block: ul}
I/flutter ( 2915):   └ ¶ ⟨item 3⟩ ⏎ {block: ul}

this is zefyr document output to Delta

I/flutter ( 2915): insert⟨ hello ⟩ + {b: true}
I/flutter ( 2915): insert⟨ ⏎this is list ⟩
I/flutter ( 2915): insert⟨ ⏎ ⟩ + {heading: 2}
I/flutter ( 2915): insert⟨ ⏎item 1 ⟩
I/flutter ( 2915): insert⟨ ⏎ ⟩ + {block: ul}
I/flutter ( 2915): insert⟨ item 2 ⟩
I/flutter ( 2915): insert⟨ ⏎ ⟩ + {block: ul}
I/flutter ( 2915): insert⟨ item 3 ⟩
I/flutter ( 2915): insert⟨ ⏎ ⟩ + {block: ul}

and this is notusMarkDown.decode output

I/flutter ( 2915): insert⟨ hello ⟩ + {b: true}
I/flutter ( 2915): insert⟨ ⏎this is list⏎------------⏎ ⟩
I/flutter ( 2915): insert⟨ item 1⏎item 2⏎item 3⏎ ⟩ + {block: ul}

and if i set markdown headingStyle to 'atx' the output look like this

I/flutter ( 2915): insert⟨ hello ⟩ + {b: true}
I/flutter ( 2915): insert⟨ ⏎ ⟩
I/flutter ( 2915): insert⟨ this is list⏎ ⟩ + {heading: 2}
I/flutter ( 2915): insert⟨ item 1⏎item 2⏎item 3⏎ ⟩ + {block: ul}

if i set headingStyle to 'atx' zefyr throw that error but i set it to 'setext' zefyr cant render it and show dashes in the editor thank you

ghost commented 4 years ago

Good luck to all!

On Sunday, February 16, 2020, amir moghadam notifications@github.com wrote:

i use @nalbion https://github.com/nalbion solution https://github.com/memspace/zefyr/issues/186#issuecomment-545859501 and i can edit html with zefyr and export as html i get html from api convert it to markdown with html2md package then convert it to Delta with notusMarkdown.decode(markdown) and show it with NotusDocument.fromDelta its ok until your html contain heading or list and if your html contain those, this error throwing

The following assertion was thrown building Builder: Style cannot be applied to this leaf node: {block: ul} 'package:notus/src/document/leaf.dart': Failed assertion: line 106 pos 12: 'value != null && (value.isInline || value.isEmpty)'

what can i do ? anyone know another way or any solution to solve this problem ? thanks for your help

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/memspace/zefyr/issues/250?email_source=notifications&email_token=ALLZTYR73CI3AX2BJWEPJHDRDEWDJA5CNFSM4KWCWKLKYY3PNVWWK3TUL52HS4DFUVEXG43VMWVGG33NNVSW45C7NFSM4IN2457Q, or unsubscribe https://github.com/notifications/unsubscribe-auth/ALLZTYWC2KEFBW35WNIIBJLRDEWDJANCNFSM4KWCWKLA .

cgestes commented 4 years ago

Are you missing a \n before the beginning of your list?

veneno261 commented 4 years ago

which list did you mean ?

and as far as i know the \n before beginning not required

cgestes commented 4 years ago

I/flutter ( 2915): insert⟨ hello ⟩ + {b: true} I/flutter ( 2915): insert⟨ ⏎ ⟩ I/flutter ( 2915): insert⟨ this is list⏎ ⟩ + {heading: 2} <<<<<HERE I/flutter ( 2915): insert⟨ item 1⏎item 2⏎item 3⏎ ⟩ + {block: ul}

veneno261 commented 4 years ago

its decoded with notusMarkdown.decode(markdown) but i try to add this line manually and tell you what happen

veneno261 commented 4 years ago

@cgestes i do it but throw that error again

cgestes commented 4 years ago

each items should be a separate ul block then?

veneno261 commented 4 years ago

i wrote this decoder and its better than notusMarkdown.decode(markdown) but it decode notusMarkdown output

NotusDocument _loadNotes() {
    var markdown = html2md.convert(
      widget.text,
      styleOptions: {
        'headingStyle': 'atx'
      }
    );

    if (markdown == null || markdown == '') {
      return NotusDocument();
    }

    Delta delta = notusMarkdown.decode(markdown);
    Delta deltaTwo = Delta();

    delta.toList().forEach((val){

      if(val.data.contains('* *\n') && val.hasAttribute('block')){
        /// not work because 'Embed style can only be applied to an EmbedNode.'
        deltaTwo.insert('', {'embed': {'type': 'hr'}});
      }
      else if(val.hasAttribute('heading')) {
        deltaTwo.insert(val.data.trim());
        deltaTwo.insert('\n', val.attributes);
      }
      else if(val.hasAttribute('block')){

        val.data.split('\n').forEach((item){

          if(!val.data.contains('\n')) {

            Map<String, dynamic> tempAttr = {};

            val.attributes.forEach((key, value){
              if(key != 'block')
                tempAttr.addAll({key: value});
            });

            deltaTwo.insert(item, tempAttr.isNotEmpty ? tempAttr : null);

          }
          else if(item.trim().isNotEmpty) {
            deltaTwo.insert(item);
            deltaTwo.insert('\n', val.attributes);
          }

        });

      }else
        deltaTwo.insert(val.data, val.attributes);

    });
    deltaTwo.insert('\n');

    return NotusDocument.fromDelta(deltaTwo);
  }
sumitbhanushali commented 4 years ago

getting similar error but for blockquote, I have used similar setup

Style cannot be applied to this leaf node: {block: quote}
'package:notus/src/document/leaf.dart':
Failed assertion: line 106 pos 12: 'value != null && (value.isInline || value.isEmpty)'
jclink commented 3 years ago

Not sure if this will help, but certain attributes may require the addition of '\n'. For example, I use the 'heading' attribute like this: Operation.insert('text'); Operation.insert('\n', {"heading": 1}); I ran into problems using Operation.insert('text\n', {'heading': 1});, but extracting the '\n' worked great.