zefyr icon indicating copy to clipboard operation
zefyr copied to clipboard

edit html with zefyr and notus

Open veneno261 opened this issue 5 years ago • 12 comments

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

veneno261 avatar Feb 16 '20 12:02 veneno261

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?

cgestes avatar Feb 16 '20 15:02 cgestes

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

veneno261 avatar Feb 17 '20 06:02 veneno261

Good luck to all!

On Sunday, February 16, 2020, amir moghadam [email protected] 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 .

ghost avatar Feb 17 '20 08:02 ghost

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

cgestes avatar Feb 17 '20 12:02 cgestes

which list did you mean ?

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

veneno261 avatar Feb 17 '20 12:02 veneno261

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}

cgestes avatar Feb 17 '20 12:02 cgestes

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

veneno261 avatar Feb 17 '20 13:02 veneno261

@cgestes i do it but throw that error again

veneno261 avatar Feb 17 '20 13:02 veneno261

each items should be a separate ul block then?

cgestes avatar Feb 17 '20 13:02 cgestes

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);
  }

veneno261 avatar Feb 20 '20 06:02 veneno261

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)'

sumitbhanushali avatar Jun 09 '20 15:06 sumitbhanushali

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.

jclink avatar Jan 16 '21 13:01 jclink