Tasfer: a text editor drawn on a 2D canvas

(hamza.se)

48 points | by hamza512b 3 days ago

18 comments

  • annex-winged-cr 5 minutes ago
    Just tested it on Android, glide delete and glide cursor control doesn't work.

    Would it even be possible to make those work with a canvas?

  • hnlmorg 2 hours ago
    This looks slick but I think you need a better way to market it.

    The 2D canvas part is the norm for anyone who wants performance. Working with the DOM becomes painfully slow and resource intensive the moment you add syntax highlighting, spell checking, and other visual chrome, to large documents.

    This is why Monaco (the editor widget behind VSCode) is a canvas. Why terminal emulators built with web technologies use canvas. And so on.

    So I wouldn’t say the canvas part of the heading is a differentiator.

    Edit: apologies, seems I was wildly wrong here. Please disregard the above.

    • chrismorgan 1 hour ago
      > The 2D canvas part is the norm for anyone who wants performance. Working with the DOM becomes painfully slow and resource intensive the moment you add syntax highlighting, spell checking, and other visual chrome, to large documents.

      This is wildly wrong. 2D canvas is consistently slower than letting the browser handle the rendering, so long as you avoid making the DOM too complex, and possibly monitor the viewport and only keep some of the content in the DOM at a time (though for most applications this practice is somewhere between harmful and not useful, and it definitely adds a lot of complexity).

      > This is why Monaco (the editor widget behind VSCode) is a canvas.

      It isn’t.

      > Why terminal emulators built with web technologies use canvas.

      Why on earth would you build with web technology, if you’re then going to use canvas? I can’t immediately think of any that match your description (though I have no doubt that in-browser ones using canvas exist).

      • hnlmorg 1 hour ago
        > This is wildly wrong

        You’re right. I’ve been experimenting with Monaco lots lately and could have sworn it used a canvas. But it doesn’t.

        > 2D canvas is consistently slower than letting the browser handle the rendering, so long as you avoid making the DOM too complex, and possibly monitor the viewport and only keep some of the content in the DOM at a time (though for most applications it’s somewhere between harmful and not useful, and it definitely adds a lot of complexity).

        Interesting. I’ve found the reverse to be true. But it sounds like this is human error on my part. (probably doesn’t help that I’ve had more experience building high performance GPU applications in Dx, SDL, and similar than I have building high performance web apps.

        Thanks for the correction.

        > Why on earth would you build with web technology, if you’re then going to use canvas? I can’t immediately think of any that match your description (though I have no doubt that in-browser ones using canvas exist).

        You answered your own question.

        And I do know of at least one written using the canvas. Because I wrote it. I’m now interested in how others work though.

        • chrismorgan 14 minutes ago
          Most in-browser terminal emulators just use plain old boring DOM, and ignore the issue of perfect columns. Some detect it and wrap offending characters in fixed-width spans. But the entire concept of columns is unsound, doesn’t work at all for a lot of scripts.
  • gb2d_hn 2 hours ago
    This looks great. I've been impressed at how flexible CodeMirror is though. When I started EtherPK (https://app.etherpk.com) I made a bet that CodeMirror could help me build an editor that could combine outliner blocks, standard prose and rich overlays / graphics / embeds in one editor. I was concerned that I'd hit a road block (I presumed Logseq used custom HTML, nested divs and click position mapping for rendered text to the underlying input for a reason), but 9 months in I couldn't be happier with my choice, and it's a blazing fast editor that feels really nice and light to type in (live demo: https://app.etherpk.com/demo)
  • pcj-github 2 hours ago
    I wrote a similar tool to this many years ago that used JATS as an internal document model, using contentEditable, and I can relate to the pain you refer to. Getting the semantics right in cases where you split or join text that has varying types of nested context was hard.

    I like what you did here in terms of the cursor that points one way or the other: it tells you if you're in "normal" mode, or for example, in a bold region. I don't think I've seen that before so, if you made it up, that itself is a cool invention.

  • SubiculumCode 2 hours ago
    I wish Office 365 would hire someone like the author. Online Word never renders the same as it would in the Desktop software...and this matters. I deal with only modestly complex documents when I write grants but I do need to stay within page length limits for sections, I need some layout stability...so I inevitably fire up my Windows VM to run the application.

    Before anyone suggests LateX, I know, I know, but when you write collaboratively, you don't always get to choose the platform.

    • not_a_bot_4sho 58 minutes ago
      Microsoft had a blog post somewhere talking about how they're using desktop rendering code via wasm and canvas to get to parity.

      Don't know how complete that effort is though. Haven't checked myself.

    • oniony 1 hour ago
      Was actually going to suggest Typst.
  • ricardobeat 51 minutes ago
    The editor swallows all accented characters (ex áã, ö, è).
  • rpastuszak 3 hours ago
    We should chat (check bio)! For almost a decade now I’ve been working on a writing tool that might benefit from it. I build occasional forks with procgen on top it. That being said better bidi handling is something I’m most interested in.

    Enso.sonnet.io - what I’m talking about.

    (On untested.sonnet.io you’ll find notes about the experiments / toys related)

  • hridyaagrawal 1 hour ago
    how are you handling IME and screen readers with canvas? also do you relayout per line or per block? only relaying out changed blocks was the biggest typing speedup in my markdown editor
  • aziis98 3 hours ago
    Ok the custom rich text latex editor is really cool. But I'm on a tablet and stuff like selecting text is a bit awkward (the up down auto scroll is not exactly the same as the native one and isn't as precise as the native one).

    But still this is an awesome project!

  • wdb 1 hour ago
    Same thing was done in Flash back in the day :)
  • docheinestages 2 hours ago
    What UI library did you use? Looks clean.
  • chrismorgan 19 minutes ago
    This is a good demonstration of why you really shouldn’t do this. Bluntly: this is completely unusable for many people, barely usable for a lot more, and on desktop and mobile both I would absolutely hate to use this, and a lot of the problems in it fundamentally cannot be fixed.

    > But it also means the editor looks and behaves the same in every browser, on desktop and on phone, because nobody else is in charge of the pixels.

    You say this as though it were a good thing. It’s very much not; they’re not supposed to be the same, they have slightly different expected renderings, and significantly different interactions.

    And you can’t inspect or emulate them.

    —⁂—

    First of all, Firefox under Linux. I see it renders with my chosen fonts, indicating (since you’ve said you’re using 2D canvas) that you’re using fillText. Good; I would complain more about the alternative. But it does kinda go against a lot of what you said about who was in charge of the pixels.

    I use my Compose key. Underlined · placeholders, proper replacement, &c. Huh, you’ve surprised me by actually handling that correctly. Well done.

    Though I do note that when I type U+1F928 FACE WITH ONE EYEBROW RAISED in a title, in the app’s sidebar and top-of-page title it becomes U+1F929 GRINNING FACE WITH STAR EYES. That’s… not encouraging, but ultimately presumably Just a Bug.

    I switch to Telugu and type “telugu”, తెలుగు. Uh oh… with each new consonant it drops the completed syllable, and when I press Escape at any point it deletes the composition. Utterly debilitating bug for IME usage, but ultimately fixable.

    I enter some text, find that for the most part it works significantly better than I expected, even handling things like clipboards pretty well.

    Then I turn to what I know it will fail, because it’s not possible to get correct universally (different platforms have different behaviours and you can’t probe it; user-agent/platform sniffing would get the best results): keyboard navigation. Ugh, Ctrl+{Left,Right} is utterly wrong. I expected it to have implemented perhaps Windows’ behaviour and I’d complain about that, but no, it’s stopping at both the end of one word and the start of the next, which no platform has ever done. Ctrl+{Up,Down} doesn’t work by paragraphs but still by line. PageUp/PageDown kinda work but the amounts they move by are just wrong, very wrong. And so on. Cursors are frustratingly non-native the while (becomes move when hovering over selected text).

    I check whether Backspace seems sane on Telugu text. Seems to be, to my satisfaction. Ctrl+Backspace, of course, is utterly wrong like Ctrl+Left was.

    I decide to skip testing any BiDi. But I do run through some of https://lord.io/text-editing-hates-you-too/, and watch it fail vertical cursor movement, affinity, emoji modifiers… meh, BiDi is here, so I decide to test it once and oh dear while it supports the general concepts properly (including selection) it seems to think that if you give it a little bit of RtL in an LtR paragraph it should turn the paragraph RtL which is badly wrong, and then it handles other aspects of selection and keyboard interaction badly wrongly. And it already failed composition. So yeah… it failed them all, where Firefox handles them all correctly.

    I try zooming with my touchpad. Nothing happens if the cursor is over the canvas. Grr. Works but leaves the canvas blurry if the cursor is outside it. (Fixable.)

    I paste the full text of Winnie-the-Pooh <https://www.gutenberg.org/cache/epub/67098/pg67098-images.ht...>. It locks up the browser tab for several seconds. (Not fundamental, but not surprising either. The browser can handle pasting a mere 26,000 words with light markup in an instant.) And takes perhaps minutes more in the background to decide it is failing to upload all the images (and regularly goes and tries to load them again later). It also inserts blank paragraphs between every paragraph and turns italics into underscore wrapping for no apparent reason. And mangles “*** START OF THE PROJECT GUTENBERG EBOOK WINNIE-THE-POOH ***” into italic “\\\\\\ START OF … \\\\\*”. Not encouraging, though once again not particularly about canvas text editing.

    Now the document is long enough, I try scrolling. Oh no.* Scrolljacking!? That was completely unforced error! You must use a real scrolling area. Scrolling is now utterly tedious for me, because it’s not possible to implement scrolling yourself from the events exposed to you, and whatever monstrosity it’s doing instead gets the scroll rate wildly wrong and lacks inertia, so a full swipe on the touchpad gets almost a pageful instead of several plus a hundred more if done fast. Combined with it hiding its fake scrollbar until you scroll, large documents are nigh unusable. Now once again, this is not fundamental to canvas text editing, so long as you’re willing to put the thing in a proper scroll area that you maintain.

    I switch to Firefox for Android with the FUTO keyboard. Initially things seem to be working well, better than I expected, particularly given how I’ve observed the backing text input is generally only being given a word at a time—I think FUTO must be remembering words itself for its suggestions, working around how badly broken what it’s being given is. But then I try to shift the cursor by sliding my finger along the Space key, and it doesn’t work. I switch to something else and come back, and selection is shot, it’s lost the caret and I don’t know what happened to it, and various keyboard interactions are broken. I press and hold on a word to select it as always works, and… it doesn’t: no, it seems like they’ve implemented something a little more like my vague memories of iOS from when I’ve seen that; and badly at that. Correct selection is rendered tedious, unreliable, and sometimes impossible. And as for doing anything with that selection… it offers Copy, Cut, Paste. Utterly inadequate, stopping the browser from doing stuff with the text (e.g. share to another app), but unavoidable in the canvas approach.

    At this point I give up; it’s completely unusable for anything but the basics. A lot of what I complained about is just that this is buggy and incomplete, but a lot of it is also fundamentally unfixable.

    Even the buggy and incomplete parts indicate why the approach is, to put it gently, risky. But the unfixable parts—

    This is why you should only use contenteditable.

    And I didn’t even get to throttling my CPU to 400MHz to test performance. But it’s after half past midnight and I should be asleep already.

  • mrtesthah 3 hours ago
    Cool idea! I approve of the privacy oriented design. But it looks like you didn’t actually test this on iOS as automatic text correction is completely broken.

    Also your website appears to have been written and generated entirely with an LLM. That doesn’t inspire trust.

    • mbreese 3 hours ago
      There’s no better way to get a lot of testers than to have a Show HN.

      I’ll confirm - there are cursor bugs on iOS. Both on newlines and autocorrect.

      I’m personally more forgiving of an LLM “helped” site, if it looks like there was a human in the loop for the process. An LLM has more context about the design goals and architecture than the reader, so if it’s an informative page, I’m not personally bothered.

      But I’m probably in the minority.

      • mrtesthah 2 hours ago
        A human is needed to show how app’s technical features are relevant to a particular audience with a shared social context. As the LLM is not (and should not ever be) a participant in that social environment, any marketing it generates will almost certainly land as tone deaf or presumptuous.
        • hnlmorg 2 hours ago
          That’s the “human in the loop” part. Use the LLM to generate a copy and the human to refine it.

          If you think successful campaigns these days are always entirely done by humans, then I’m afraid you’re mistaken.

  • enoch_hou 2 hours ago
    [flagged]
  • prodmevin 3 days ago
    [dead]
  • fwip 3 hours ago
    [flagged]