memspace / zefyr

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

My partial solution to transform NotusDocument to HTML ( code inside ) #460

Open angelserranoperez opened 3 years ago

angelserranoperez commented 3 years ago

This is a fuc*ing problem that I want to share my partial solution: It is only for heading 2, heading 3, bold, code, quote, normal text and ol. This is because in my solution I only use that parameters, but you can easily put italic and others.

It is a solution that doesn't take care of big o notation because it is only for small text.

The global scope is the following: > DocumentToTranslate ==>

'¶ ⟨Zefyr example of how to convert to html⟩ ⏎ {heading: 2}¶ ⟨Why use Zefyr : because ⟩ → ⟨you can edit text like a charm⟩b ⏎§ {ol} ├ ¶ ⟨You dont have better alternative⟩ ⏎ {heading: 2, block: ol} ├ ¶ ⟨Name Zefyr sounds like magic⟩ ⏎ {block: ol} └ ¶ ⟨What day is today?⟩ ⏎ {block: ol}§ {code} ├ ¶ ⟨Magic code for solving that f* problem⟩ ⏎ {block: code} └ ¶ ⟨Thanks to the stars⟩ ⏎ {block: code}§ {quote} └ ¶ ⟨Better known program that hundred to discover⟩ ⏎ {block: quote}';

> Result ==>

Zefyr example of how to convert to html


Why use Zefyr : because you can edit text like a charm

  1. You dont have better alternative
  2. Name Zefyr sounds like magic
  3. What day is today?

Magic code for solving that f* problem

Thanks to the stars

Better known program that hundred to discover

HERE IS THE CODE TO TRANSFORM DELTA OR NOTUS DOCUMENT TO HTML:

agruparDoc(documento) {
    var grupos = [];
    var tam = documento.length;
    var index = 0;
    buscarSiguiente(pos) {
      for (var ia = pos; ia < tam; ia++) {
        var condicion = ((documento[ia] == '¶' &&
                !documento[ia - 1].contains(RegExp(r'(⏎)')) &&
                !documento[ia - 2].contains(RegExp(r'(├|└|⏎)'))) ||
            ia == tam - 1);
        if (documento[ia] == '§' || condicion) {
          return ia;
        }
      }
    }

    buscarSiguienteDePi(pos) {
      for (var ib = pos; ib < tam; ib++) {
        var condicion = (documento[ib] == '¶' &&
                !documento[ib - 1].contains(RegExp(r'(⏎)')) &&
                !documento[ib - 2].contains(RegExp(r'(├|└|⏎)'))) ||
            documento[ib] == '§' ||
            ib == tam - 1;
        if (condicion) {
          return ib;
        }
      }
    }

    for (var i = index; i < tam; i++) {
      if (documento[i] == '§') {
        var inicio = index;
        var fin = buscarSiguiente(inicio + 1);
        grupos.insert(grupos.length, documento.substring(inicio, fin));
        index = fin;
        i = index;
      } else {
        if (documento[i] == '¶') {
          var inicio = index;
          var fin = buscarSiguienteDePi(inicio + 1);
          grupos.insert(grupos.length, documento.substring(inicio, fin));
          index = fin;
          i = index;
        }
      }
    }
    return grupos;
  }

  traducirTerminal(terminal) {
    var terminalfinal = terminal.replaceAll(RegExp(r'⏎¶|⏎'), '⟨<br/>⟩');
    String html = '';
    RegExp(r'⟨(.*?)⟩(.)')
        .allMatches(terminalfinal.split('¶')[1])
        .toList()
        .forEach((element) {
      html = html +
          (element.group(0).contains('⟩b')
              ? '<b>' +
                  element.group(0).replaceAll(RegExp(r'(⟨|⟩b)'), '') +
                  '</b>'
              : element.group(0).replaceAll(RegExp(r'(⟨|(⟩\s))'), ''));
    });
    if (terminal.contains('block: ol')) {
      html = '<ol><li>' + html + '</li></ol>';
    }
    if (terminal.contains('heading: 2')) {
      html = '<h2>' + html + '</h2>';
    }
    if (terminal.contains('heading: 3')) {
      html = '<h3>' + html + '</h3>';
    }
    if (terminal.contains('block: quote')) {
      html = '<blockquote>' + html + '</blockquote>';
    }
    if (terminal.contains('block: code')) {
      html = '<code>' + html + '</code>';
    }

    html = html + '<br/>';
    return html;
  }

  traducirGrupo(grupo) {
    String html = '';
    grupo.split('¶').asMap().forEach((index, elem) {
      if (index >= 1) {
        html = html + traducirTerminal('¶ ' + elem);
      }
    });
    if (grupo.split('¶').asMap()[0].contains('{quote}')) {
      html = html.replaceAll(RegExp(r'<br/>'), '');
      html = '<blockquote>' +
          html.replaceAll(RegExp(r'blockquote>'), 'p>') +
          '</blockquote>';
    }
    if (grupo.split('¶').asMap()[0].contains('{code}')) {
      html = html.replaceAll(RegExp(r'<br/>'), '');
      html = '<code>' + html.replaceAll(RegExp(r'code>'), 'p>') + '</code>';
    }
    if (grupo.split('¶').asMap()[0].contains('{ol}')) {
      html = html.replaceAll(RegExp(r'<br/>'), '');
      html = '<ol>' + html.replaceAll(RegExp(r'<ol>|</ol>'), '') + '</ol><br/>';
    }
    return html;
  }

// documentoATransformar is created by: 
// documentoATransformar = NotusDocument.fromDelta(_controller.document.toDelta()).toString();
 String documentoATransformar =  '¶ ⟨Zefyr example of how to convert to html⟩ ⏎ {heading: 2}¶ ⟨Why use Zefyr : because ⟩ → ⟨you can edit text like a charm⟩b ⏎§ {ol}  ├ ¶ ⟨You dont have better alternative⟩ ⏎ {heading: 2, block: ol}  ├ ¶ ⟨Name Zefyr sounds like magic⟩ ⏎ {block: ol}  └ ¶ ⟨What day is today?⟩ ⏎ {block: ol}§ {code}  ├ ¶ ⟨Magic code for solving that f* problem⟩ ⏎ {block: code}  └ ¶ ⟨Thanks to the stars⟩ ⏎ {block: code}§ {quote}  └ ¶ ⟨Better known program that hundred to discover⟩ ⏎ {block: quote}';

  var html = '';
  agruparDoc(documentoATransformar).forEach((element) {
    if (element.contains('§')) {
      html = html + traducirGrupo(element);
    } else {
      html = html + traducirTerminal(element);
    }
  });
  print('cojones');
  print(html);
angelserranoperez commented 3 years ago

If you have problems with terminal problems try to add that (because sometimes I get a bit crazy and forget to add things):

                  var html = '';
                  agruparDoc(mierda1).forEach((element) {
                    if (element.contains('§')) {
                      html = html + traducirGrupo(element);
                    } else {
                      // ******** THIS ***************
                      element.split(RegExp(r'¶')).forEach((e) {
                        html = html + traducirTerminal('¶ ' + e);
                      });
                      // *************

                    }
                  });
                  print('cojones');
                  print(html);
britannio commented 3 years ago

Have you tried https://pub.dev/packages/notustohtml?

angelserranoperez commented 3 years ago

Have you tried https://pub.dev/packages/notustohtml?

That was my first approach : later I discover that there was a dependency conflict.

singerdmx commented 3 years ago

It is also possible to do it at server side. We found a Golang package to do it https://github.com/singerdmx/BulletJournal/commit/16fc1c2b82872a94a69880a711ed46377e9bb2d4

singerdmx commented 3 years ago

Zefyr's library won't work since it is missing a lot of attributes.