Skip to content

Instantly share code, notes, and snippets.

View zurfyx's full-sized avatar

Gerard Rovira zurfyx

View GitHub Profile
@zurfyx
zurfyx / lexical-y.md
Last active October 25, 2026 23:09
@lexical/y: Lexical collaboration on Yjs 14

@lexical/y: Lexical collaboration on Yjs 14

A summary of the new collaboration binding: how it stores documents, what it keeps when people and agents edit at once, the decisions behind it, and how it compares with @lexical/yjs and other editors.

The idea in one minute

  • What it is. @lexical/y is a new, opt-in collaboration binding for Lexical on Yjs 14. @lexical/yjs stays as it is. It targets documents that people and AI agents edit at the same time, through the editor or a server-side API.
  • What's different. Text is stored flat, with a small marker at the end of each block. Splitting, joining or retyping a block only touches a marker, so a collaborator's typing survives restructuring. In every tree-based binding we compared, it doesn't.
  • What it costs. A 10,000-edit session takes 217 KB instead of 2.8 MB. Keystroke speed matches the current binding. The binding is larger than the others (about 11.7k lines with comments) because it keeps typing through restructures.
@zurfyx
zurfyx / index.js
Created October 2, 2026 17:50
Slack PWA Tampermonkey
// ==UserScript==
// @name Slack PWA fixes
// @namespace https://app.slack.com/
// @version 1.2.0
// @description Title bar matched to Slack's top bar (and hideable); white sidebar; no help button; sidebar sections capped at 5 with Show more / Show less; chat capped at a readable line length.
// @match https://app.slack.com/*
// @run-at document-start
// @noframes
// @grant none
// @sandbox JavaScript
@zurfyx
zurfyx / README.md
Last active February 23, 2026 16:22
Beautify Facebook Messages (Messenger) TamperMonkey script -- Note that Messenger.com won't be available after April 14, 2026

@zurfyx
zurfyx / .gitconfig
Last active August 12, 2026 18:35
Dot files
[user]
name = Gerard Rovira
email = gerard.rovira.sanchez@gmail.com
[gpg]
program = gpg2
[alias]
tree = log --oneline --graph --color --all --decorate
sbranch = for-each-ref --count=10 --sort=-committerdate refs/heads/ --format='%(refname:short)'
pr = "!f() { if [ $# -lt 1 ]; then echo \"Usage: git pr <id> [<remote>] # assuming <remote>[=origin] is on GitHub\"; else git checkout -q \"$(git rev-parse --verify HEAD)\" && git fetch -fv \"${2:-origin}\" pull/\"$1\"/head:pr/\"$1\" && git checkout pr/\"$1\"; fi; }; f"
ac = "!f() { git add . && git commit -m \"$*\"; }; f"
@zurfyx
zurfyx / typing-perf.js
Created October 4, 2025 16:26
Measure typing performance (copy-paste on devtools)
const validInputTypes = new Set([
"insertText",
"insertCompositionText",
"insertFromComposition",
"insertLineBreak",
"insertParagraph",
"deleteCompositionText",
"deleteContentBackward",
"deleteByComposition",
"deleteContent",
@zurfyx
zurfyx / google-play-books-minimalistic.js
Last active July 14, 2024 15:56
Google Play Books Minimalistic - TamperMonkey
// ==UserScript==
// @name Google Play Books Minimalistic
// @namespace http://tampermonkey.net/
// @version 1
// @description
// @author zurfyx
// @homepageURL https://gist.github.com/zurfyx/bc39aa7119d1ebbc469daee7c04fd0fd
// @match https://books.googleusercontent.com/books/reader/frame*
// @grant none
// ==/UserScript==
@zurfyx
zurfyx / README.md
Created July 21, 2023 18:57
Lexical Offline (Multi) Selection

The EditorState is always synced with other parties via Collab, and part of the clipboard logic.

There's times when the result should be kept strictly offline. For example:

  1. Search or multi text search (i.e. VSCode find all). Or to show GenAI GPT results.
  2. Other player cursors in Collab (not part of th EditorState)
  3. GenAI GPT Office/Notion-like popover on edit when the prompt refers to a specific part of the edit but the focus has moved to the modal.

This solution leverages Range to follow DOM updates and render on top of the Lexical editor completely independently from the editor. The MutationObserver introduced below is particularly important to make sure that the position is always up-to-date. For example, additional changes in the padding or additional added/removed nodes somewhere on the contenteditable or immediately before our selection host.

The editor dependency is very lightweight, it could easily be decoupled completely.

type LexicalNodeType2<Type> = $ReadOnly<{
type: Type,
...
}>;
export type SerializedXNode = $ReadOnly<{
// children: Array<SerializedNode>,
direction: 'ltr' | 'rtl' | null,
format: number,
indent: number,
@zurfyx
zurfyx / Invid.sol
Created February 24, 2019 16:20
InVID Rights Management Smart Contract
pragma solidity ^0.4.24;
import "./Ownable.sol";
/**
* @title Contract to register reuse requests on the InVID Rights Management site.
* @dev This contract stores the various request requests and their parties, as well as each of the
* reuse request steps that were taken during the negotiation process.
* The reuse request terms for each of the steps can be found on IPFS.
*/
@zurfyx
zurfyx / react-context-tools.js
Last active January 13, 2019 13:56
React Context Tools (provideBundle, connect, useLocalStorage)
import React, { Fragment, useState } from 'react';
/**
* Plug in many providers with a single component.
* Use:
* const Providers = provideBundle(ThemeProvider, LanguageProvider);
* <Providers>
* <YourComponent></YourComponent>
* </Providers>
*/