- From: Nicolò Ribaudo via GitHub <sysbot+gh@w3.org>
- Date: Sat, 26 Oct 2024 16:38:26 +0000
- To: public-css-archive@w3.org
nicolo-ribaudo has just created a new issue for https://github.com/w3c/csswg-drafts: == [css-highlight-api] Feedback: the global registry string-keyed makes usage very hard == Example use case: I have a contenteditable `div` that marks as `::highlight(has-x)` all the words that contain `x`. The simplest way of doing it is: ```js function highlightWords(div) { const highlight = new Highlight(); for (const child of div.childNodes) { if (child.nodeType !== Node.TEXT_NODE) continue; const regexp = /\w*x\w*/g; let match; while (match = regexp.exec(child.textContent)) { const range = document.createRange(); range.setStart(node, match.index); range.setEnd(node, match[0].length + match.index); highlight.add(range); } } CSS.highlights.set("has-x", highlight); } highlightWords(myElement); myElement.addEventListener("input", () => highlightWords(myElement)); ``` This works perfectly as long as I only call this function once on a single element. One day I decide that actually, I need this behavior on two different elements on my page, so I try doing this: ```js highlightWords(myElement1); myElement1.addEventListener("input", () => highlightWords(myElement1)); highlightWords(myElement2); myElement1.addEventListener("input", () => highlightWords(myElement2)); ``` Except that this doesn't work at all: the highlighting logic over `myElement1` and `myElement2` fight over control of the `has-x` entry in the global `CSS.highlights` registry, and delete each other's highlights as they get updated. To make it work, I need to instead update the logic in `highlightWords` to _never_ overwrite an existing entry in the `CSS.highlights` map. Instead, it must check through all the ranges in the entry and only remove/add its own, and then _if the map ends up being empty_ it can remove it. The global registry introduces a synchronization point between different parts of the page that is easier to get wrong than it's to get right, and if you are a library author (for example, publishing the logic above in a custom element) you won't notice unless you explicitly test multiple instances on the same page. --- There are multiple ways that the API can be changed to make it difficult to do the wrong thing. **Do not allow reading `Highlight` objects from the global registry, and do not allow removing `Highlight` objects that you do not control**: - `.get()` is removed - to check whether an highlight has been registered, you have to do `CSS.highlights.has(name, highlight)` instead of `CSS.highlights.has(name)` - `.set(name, highlight)` throws if there is already an entry called `name` - to delete an highlight, you must use `.delete(name, highlight)` instead of `.delete(name)` This keeps the synchronization complexity, but forces developers to think about it. **Allow registering multiple `Highlights` with the same name**: Similar to above, except that instead of it makes conflicts work well together instead of overwriting each other - `.get()` is removed, or it returns an array of `Highlight` objecs - to check whether an highlight has been registered, you have to do `CSS.highlights.has(name, highlight)` instead of `CSS.highlights.has(name)` - `.set(name, highlight)` adds a new highlight named `name`, without removing any existing highlight with the same name. - to delete an highlight, you must use `.delete(name, highlight)` instead of `.delete(name)` **Allow using local registries** Allow the function above to create its own `highlights` registry by doing something like `const highlights = new HighlightsRegistry(document)`. Different registries can declare the same name without conflicting with each other. The example above would become ```js const registry1 = new HighlightsRegistry(document); highlightWords(registry1, myElement1); myElement1.addEventListener("input", () => highlightWords(registry1, myElement1)); const registry2 = new HighlightsRegistry(document); highlightWords(registry2, myElement2); myElement1.addEventListener("input", () => highlightWords(registry2, myElement2)); ``` Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/11095 using your GitHub account -- Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config
Received on Saturday, 26 October 2024 16:38:27 UTC