Hacker Newsnew | past | comments | ask | show | jobs | submit | bikeshaving's commentslogin

I’ve tried to create the minimalist version of this with Revise.js. The main surface area is a custom element called a `<content-area>`. The OverType library you linked to uses a time-old technique where you essentially put a duplicate copy of the content over a `<textarea>` to highlight it but this doesn’t really work in mobile and it messes with the selection. I’ve tried to grapple with `contenteditable` directly with my solution, but it does try to use less JavaScript and it does try to be more minimal.

https://github.com/bikeshaving/revise https://revise.js.org https://revise.js.org/blog/introducing-revise/


Just wanted to say, I enjoyed the article and your minimal rich text editor library looks great! I've been working with heavily customized code editors (mostly CodeMirror from previous major versions to current) and rich text editors (Quill, etc.) for years now, off and on. For various reasons I keep coming back to building a new editor, sometimes in the terminal for a REPL with syntax highlight, or a Markdown editor in the browser, other times attempting a content editor with media blocks. CodeMirror and ProseMirror are impressive works and my current go-to libraries, but I'd love to try a light-weight approach from the bottom up, small enough to be able to understand it completely.

Read your blogpost, I will need a code editor soon so I might have a stab at hacking something together.

> but this doesn’t really work in mobile and it messes with the selection

I haven't tested it personally, but on the OverType they claim "excellect mobile support".


I’ve written about how Svelte, Vue, and Solid are all reactive and share common pitfalls due to their reactive solutions. My theory is that they all cause worse bugs than they prevent.

https://crank.js.org/blog/why-be-reactive/


Compared to what? I mean, what's the alternative for an interactive app?


Manual refresh(). This is something Crank does, and other frameworks like the new Remix one is picking it up as well. Being explicit has its advantages.


I’m very wary of celebrating Meta’s language work when the company was credibly found to have contributed to the genocide against the Rohingya in Myanmar, and separately, to human rights abuses against Tigrayans during the conflict in northern Ethiopia. Be careful whose sins you’re laundering.

https://www.amnesty.org/en/latest/news/2025/02/meta-new-poli... https://www.amnesty.org/en/latest/news/2023/10/meta-failure-...


I had the same reaction to this post. Mainly because one of Meta's explanations for the lapse was that they didn't have moderators who understood the local language

You hear that folks? Lack of localization kills.


Do you also boycott Toyota for the Hilux?


I don’t own a car :)


I must tell you, it is an incredible relief to learn that McZee was not a figment of my imagination.


Just found the text editor from my childhood


I keep asking why the default Claude tools like Read(), Write(), Edit(), MultiEdit(), Replace() tools aren’t just Bash() with some combination of cat, sed, grep, find. Isn’t it just easier to pipe everything through the shell? We just need to figure out the permissions for it.


Because the Tools model allows for finer grained security controls than just bash and pipe. Do you really want Claude doing `find | exec` instead of calling an API that’s designed to prevent damage?


It might be the wrong place to do security anyway since `bash` and other hard-to-control tools will be needed. Sandboxing is likely the only way out


not for every user or use case. when developing of course i run claude —-do-whatever-u-want; but in a production system or a shared agent use case, im giving the agent least privilege necessary. being able to spawn POSIX processes is not necessary to analyze OpenTelemetry metric anomalies.


yeah, I would rather it did that. You run Claude in a sandbox that restricts visibility to only the files it should know about in the first place. Currently I use a mix of bwrap and syd for filtering.


Making those tools first-class primitives is good for (human) UX: you see the diffs inline, you can add custom rules and hooks that trigger on certain files being edited, etc.


I’ve found that humans are pretty good at reading through the output of bash commands. And Claude Code keeps insisting on truncating the output for some reason.


A long time ago, I wrote an abstraction called a Repeater. Essentially, the idea behind it is, what would the Promise constructor look like if it was translated to async iterables.

  import { Repeater } from "@repeaterjs/repeater";
  
  const keys = new Repeater(async (push, stop) => {
    const listener = (ev) => {
      if (ev.key === "Escape") {
        stop();
      } else {
        push(ev.key);
      }
    };
    window.addEventListener("keyup", listener);
    await stop;
    window.removeEventListener("keyup", listener);
  });
  const konami = ["ArrowUp", "ArrowUp", "ArrowDown", "ArrowDown", "ArrowLeft", "ArrowRight", "ArrowLeft", "ArrowRight", "b", "a"];
  (async function() {
    let i = 0;
    for await (const key of keys) {
      if (key === konami[i]) {
        i++;
      } else {
        i = 0;
      }
      if (i >= konami.length) {
        console.log("KONAMI!!!");
        break; // removes the keyup listener
      }
    }
  })();
https://github.com/repeaterjs/repeater

It’s one of those abstractions that’s feature complete and stable, and looking at NPM it’s apparently getting 6.5mil+ downloads a week for some reason.

Lately I’ve just taken the opposite view of the author, which is that we should just use streams, especially with how embedded they are in the `fetch` proposals and whatever. But the tee critique is devastating, so maybe the author is right. It’s exciting to see people are still thinking about this. I do think async iterables as the default abstraction is the way to go.


In the repeater callback, you're both calling the stop argument and awaiting it. Is it somehow both a function and a promise? Is this possible in JS?

edit: I found where stop is created[1]. I can't say I've seen this pattern before, and the traditionalist in me wants to dislike the API for contradicting conventions, but I'm wondering if this was designed carefully for ergonomic benefits that outweigh the cost of violating conventions. Or if this was just toy code to try out new patterns, which is totally legit also

[1]: https://github.com/repeaterjs/repeater/blob/638a53f2729f5197...


Yes, the callable promise abstraction is just a bit of effort:

  let resolveRef;
  const promise = new Promise((res) => { resolveRef = res; });
  
  const callback = (data) => {
    // Do work...
    resolveRef(data); // This "triggers" the await
  };

  Object.assign(callback, promise);

There’s a real performance cost to awaiting a fake Promise though, like `await regularPromise` bypasses the actual thenable stuff.


It's not common, but there are web APIs where you await a promise that already exists as a property, rather than being returned from a function call, like

    await document.fonts.ready

    device.lost.then(() => {
      console.log('WebGPU device lost :(')
    })
I feel like this isn't confusing if you know how promises work, but maybe it can be confusing for someone coming from Python/Rust, where async functions don't evaluate until their futures are awaited.


Off topic - But just wanna say - Love the cheat code! 30 Lives added :-) Nostalgia runs deep with that code. So deep - in fact, that I sign many of my emails off with "Sent by hitting Up, Up, Down, Down, Left, Right, Left, Right, B, A"


Off topic to the off topic, but that logic doesn't look right. It seems like if up is pressed, you might need to reset i to 1 or 2, not 0.


Not accepting PRs for this. I think the logic is sound (Easter Eggs should be difficult to trigger).


Can anyone who works with the Unicode consortium explain why Cistercian numerals aren’t just part of Unicode? There’s Aegean numbers, counting rod numerals, Mayan numerals, Roman numerals (beyond the Latin letter aliases), cuneiform numbers, and plenty of other historical numeral-only systems.

The 4-stave system is interesting but can almost certainly be done using ZWJ hacks maybe.


From the Script Ad Hoc Group: https://www.unicode.org/L2/L2021/21016-script-adhoc-rept.pdf

"A project to digitize Cistercian manuscripts at Western Michigan University is not requesting the characters be in Unicode, so this is just an informational document. [...] We recommend the UTC make the following disposition: Notes this document (L2/20-290) but takes no further action."

For something to be added to Unicode, someone actually has to request it and shepherd it through the process.


My immediate thought was combining characters eg

  934 = CISTERCIAN STAFF + 
        COMBINING CISTERCIAN 900 +
        COMBINING CISTERCIAN 30 +
        COMBINING CISTERCIAN 4
Would require allocating (1 staff) + (9 digits) * (4 places) = 37 code points.

Were you thinking

  934 = CISTERCIAN 900 +
        ZWJ + 
        CISTERCIAN 30 +
        ZWJ +
        CISTERCIAN 4

?


I was thinking using ZWJ because the staff is always implied by the usage of Cistercian numerals. I was also wondering if we could reuse CISTERCIAN 1-9 for each significant digit rather than having to encode all 4 separately, though at the end of the day it’s only 36 separate code points.

Adding the staff is 37 codepoints versus 36, but I think using ZWJ would at least have each numeral independently renderable so it degrades gracefully. I’m not too sure about how combining characters degrade.

Essentially it boils down to whether you think the staff and the digit flag part of the numeral are independent or not.


Thanks for the kind words! Let me know your thoughts if you end up exploring.


I’ve just published the first public release of a new open source project Shovel.js, replacing tools like Express, Fastify, Next.js, Vite. It’s a full-stack/meta server framework which implements the full Service Worker specification but in Node, Bun, Cloudflare. It leans into using web standards to do things like accessing the filesystem, reading cookies, create client-side bundles rather than inventing new APIs. You can read about the process of making Shovel with AI in the introductory blog post.

https://shovel.js.org/blog/introducing-shovel/

https://github.com/bikeshaving/shovel


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: