{"_id":"@emergence-engineering/prosemirror-who-wrote-what","_rev":"3-18ea7cdf74b1a0809fce52fcf3ec9f8f","name":"@emergence-engineering/prosemirror-who-wrote-what","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.0":{"name":"@emergence-engineering/prosemirror-who-wrote-what","version":"0.1.0","keywords":["ProseMirror","Yjs","collaboration","authorship","decorations"],"author":{"name":"Emergence Engineering"},"license":"ISC","_id":"@emergence-engineering/prosemirror-who-wrote-what@0.1.0","maintainers":[{"name":"matejcsok","email":"istvan.matejcsok@emergence-engineering.com"},{"name":"viktorvacziee","email":"viktor.vaczi@emergence-engineering.com"},{"name":"tg44","email":"torcsvari.gergo@gmail.com"},{"name":"cskata","email":"katalin.csillag@emergence-engineering.com"}],"homepage":"https://github.com/emergence-engineering/emergence-tools/tree/main/packages/prosemirror-who-wrote-what#readme","bugs":{"url":"https://github.com/emergence-engineering/emergence-tools/issues"},"dist":{"shasum":"1cf3fae4639826da42b7d61954f71ee178f37224","tarball":"https://registry.npmjs.org/@emergence-engineering/prosemirror-who-wrote-what/-/prosemirror-who-wrote-what-0.1.0.tgz","fileCount":14,"integrity":"sha512-ZpydC8Roa7icKyhz2jgs8JtkWUCkpjpUD3YOc7kkz+63517eyvmAIa9lus3GW+rrmH2Fsxq4/uPvUrIWP+WJ0A==","signatures":[{"sig":"MEUCIHPe33SVZrHZT3euT+v8SMqVO5CxGu3xvLSO0XNjUyeEAiEAqG+bkc6qJvajw9wt4KQJbHx8ERsuYKK8x1n9AybP/jY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":20481},"main":"dist/index.js","_from":"file:emergence-engineering-prosemirror-who-wrote-what-0.1.0.tgz","types":"dist/index.d.ts","module":"dist/index.es.js","engines":{"node":">=16.0.0"},"scripts":{"dev":"rollup -c -w --bundleConfigAsCjs","e2e":"playwright test","lint":"tsc --noEmit","test":"pnpm test:e2e","build":"rollup -c --bundleConfigAsCjs","format":"eslint src --ext .ts --fix","prebuild":"rimraf dist","test:e2e":"playwright test","e2e:server":"vite --config e2e/vite.config.ts"},"_npmUser":{"name":"tg44","email":"torcsvari.gergo@gmail.com"},"_resolved":"/private/var/folders/vd/vvmzq4kn6vq7qwcgg92p1dnh0000gn/T/129fd98e9d3d8610a8d03f345a9870e4/emergence-engineering-prosemirror-who-wrote-what-0.1.0.tgz","_integrity":"sha512-ZpydC8Roa7icKyhz2jgs8JtkWUCkpjpUD3YOc7kkz+63517eyvmAIa9lus3GW+rrmH2Fsxq4/uPvUrIWP+WJ0A==","repository":{"url":"git+https://github.com/emergence-engineering/emergence-tools.git","type":"git","directory":"packages/prosemirror-who-wrote-what"},"_npmVersion":"11.6.4","description":"Track text authorship in collaborative ProseMirror editors using Yjs — highlights which user wrote which text with colored inline decorations","directories":{},"_nodeVersion":"24.11.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"yjs":"^13.6.1","vite":"^5.0.0","eslint":"^8.49.0","rimraf":"^5.0.0","rollup":"^3.29.2","prettier":"^2.8.1","typescript":"^5.2.2","y-protocols":"^1.0.6","y-prosemirror":"^1.2.1","@playwright/test":"^1.41.0","prosemirror-view":"^1.20.0","prosemirror-model":"^1.19.0","prosemirror-state":"^1.3.3","eslint-plugin-react":"^7.33.2","eslint-plugin-import":"^2.28.1","eslint-config-prettier":"^8.5.0","eslint-plugin-jsx-a11y":"^6.7.1","eslint-plugin-prettier":"^4.2.1","prosemirror-schema-basic":"^1.2.0","@typescript-eslint/parser":"^6.7.2","prosemirror-example-setup":"^1.2.0","rollup-plugin-typescript2":"^0.35.0","rollup-plugin-minification":"^0.2.0","eslint-config-airbnb-typescript":"^17.1.0","@typescript-eslint/eslint-plugin":"^6.7.2"},"peerDependencies":{"yjs":"^13.6.1","y-prosemirror":"^1.2.1","prosemirror-view":"^1.20.0","prosemirror-state":"^1.3.3"},"_npmOperationalInternal":{"tmp":"tmp/prosemirror-who-wrote-what_0.1.0_1773044144545_0.4868247248349673","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@emergence-engineering/prosemirror-who-wrote-what","version":"0.1.1","keywords":["ProseMirror","Yjs","collaboration","authorship","decorations"],"author":{"name":"Emergence Engineering"},"license":"ISC","_id":"@emergence-engineering/prosemirror-who-wrote-what@0.1.1","maintainers":[{"name":"matejcsok","email":"istvan.matejcsok@emergence-engineering.com"},{"name":"viktorvacziee","email":"viktor.vaczi@emergence-engineering.com"},{"name":"tg44","email":"torcsvari.gergo@gmail.com"},{"name":"cskata","email":"katalin.csillag@emergence-engineering.com"}],"homepage":"https://github.com/emergence-engineering/emergence-tools/tree/main/packages/prosemirror-who-wrote-what#readme","bugs":{"url":"https://github.com/emergence-engineering/emergence-tools/issues"},"dist":{"shasum":"d72616bbb2dc727177a8f03ee17c6a136338400a","tarball":"https://registry.npmjs.org/@emergence-engineering/prosemirror-who-wrote-what/-/prosemirror-who-wrote-what-0.1.1.tgz","fileCount":14,"integrity":"sha512-zP/P+b8Fvj8qFryh+K/ocuR4vIiD8erSdYkQfsAAjao7JsnRdEPU7AoFwVB5qUkaVr1uo6jYcDb2CPIcnOyedw==","signatures":[{"sig":"MEQCIFRDkDH7C2ptxJVl+fHMpu4VzLSLHZlOgEa9Ze8JbP+ZAiAjjB1PE6jNRzC+FWPi8JdsOVE1UrCPBy4atOcTIJ1LxQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":20661},"main":"dist/index.js","_from":"file:emergence-engineering-prosemirror-who-wrote-what-0.1.1.tgz","types":"dist/index.d.ts","module":"dist/index.es.js","engines":{"node":">=16.0.0"},"scripts":{"dev":"rollup -c -w --bundleConfigAsCjs","e2e":"playwright test","lint":"tsc --noEmit","test":"pnpm test:e2e","build":"rollup -c --bundleConfigAsCjs","format":"eslint src --ext .ts --fix","prebuild":"rimraf dist","test:e2e":"playwright test","e2e:server":"vite --config e2e/vite.config.ts"},"_npmUser":{"name":"tg44","email":"torcsvari.gergo@gmail.com"},"_resolved":"/private/var/folders/vd/vvmzq4kn6vq7qwcgg92p1dnh0000gn/T/8e55dca4cb8b5302b4563e2d805fd516/emergence-engineering-prosemirror-who-wrote-what-0.1.1.tgz","_integrity":"sha512-zP/P+b8Fvj8qFryh+K/ocuR4vIiD8erSdYkQfsAAjao7JsnRdEPU7AoFwVB5qUkaVr1uo6jYcDb2CPIcnOyedw==","repository":{"url":"git+https://github.com/emergence-engineering/emergence-tools.git","type":"git","directory":"packages/prosemirror-who-wrote-what"},"_npmVersion":"11.6.4","description":"Track text authorship in collaborative ProseMirror editors using Yjs — highlights which user wrote which text with colored inline decorations","directories":{},"_nodeVersion":"24.11.1","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"yjs":"^13.6.1","vite":"^5.0.0","eslint":"^8.49.0","rimraf":"^5.0.0","rollup":"^3.29.2","prettier":"^2.8.1","typescript":"^5.2.2","y-protocols":"^1.0.6","y-prosemirror":"^1.2.1","@playwright/test":"^1.41.0","prosemirror-view":"^1.20.0","prosemirror-model":"^1.19.0","prosemirror-state":"^1.3.3","eslint-plugin-react":"^7.33.2","eslint-plugin-import":"^2.28.1","eslint-config-prettier":"^8.5.0","eslint-plugin-jsx-a11y":"^6.7.1","eslint-plugin-prettier":"^4.2.1","prosemirror-schema-basic":"^1.2.0","@typescript-eslint/parser":"^6.7.2","prosemirror-example-setup":"^1.2.0","rollup-plugin-typescript2":"^0.35.0","rollup-plugin-minification":"^0.2.0","eslint-config-airbnb-typescript":"^17.1.0","@typescript-eslint/eslint-plugin":"^6.7.2"},"peerDependencies":{"yjs":"^13.6.1","y-prosemirror":"^1.2.1","prosemirror-view":"^1.20.0","prosemirror-state":"^1.3.3"},"_npmOperationalInternal":{"tmp":"tmp/prosemirror-who-wrote-what_0.1.1_1774530204277_0.6582437872627553","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@emergence-engineering/prosemirror-who-wrote-what","version":"0.2.0","description":"Track text authorship in collaborative ProseMirror editors using Yjs — highlights which user wrote which text with colored inline decorations","main":"dist/index.js","module":"dist/index.es.js","types":"dist/index.d.ts","engines":{"node":">=16.0.0"},"repository":{"type":"git","url":"git+https://github.com/emergence-engineering/emergence-tools.git","directory":"packages/prosemirror-who-wrote-what"},"author":{"name":"Emergence Engineering"},"keywords":["ProseMirror","Yjs","collaboration","authorship","decorations"],"license":"ISC","bugs":{"url":"https://github.com/emergence-engineering/emergence-tools/issues"},"homepage":"https://github.com/emergence-engineering/emergence-tools/tree/main/packages/prosemirror-who-wrote-what#readme","publishConfig":{"access":"public"},"peerDependencies":{"prosemirror-state":"^1.3.3","prosemirror-view":"^1.20.0","y-prosemirror":"^1.2.1","yjs":"^13.6.1"},"devDependencies":{"@playwright/test":"^1.41.0","@typescript-eslint/eslint-plugin":"^6.7.2","@typescript-eslint/parser":"^6.7.2","eslint":"^8.49.0","eslint-config-airbnb-typescript":"^17.1.0","eslint-config-prettier":"^8.5.0","eslint-plugin-import":"^2.28.1","eslint-plugin-jsx-a11y":"^6.7.1","eslint-plugin-prettier":"^4.2.1","eslint-plugin-react":"^7.33.2","prettier":"^2.8.1","prosemirror-state":"^1.3.3","prosemirror-view":"^1.20.0","y-prosemirror":"^1.2.1","y-protocols":"^1.0.6","yjs":"^13.6.1","prosemirror-model":"^1.19.0","prosemirror-schema-basic":"^1.2.0","prosemirror-example-setup":"^1.2.0","rimraf":"^5.0.0","vite":"^5.0.0","rollup":"^3.29.2","rollup-plugin-minification":"^0.2.0","rollup-plugin-typescript2":"^0.35.0","typescript":"^5.2.2"},"scripts":{"prebuild":"rimraf dist","build":"rollup -c --bundleConfigAsCjs","dev":"rollup -c -w --bundleConfigAsCjs","format":"eslint src --ext .ts --fix","lint":"tsc --noEmit","test":"pnpm test:e2e","test:e2e":"playwright test","e2e":"playwright test","e2e:server":"vite --config e2e/vite.config.ts"},"_id":"@emergence-engineering/prosemirror-who-wrote-what@0.2.0","_integrity":"sha512-B3Y1jD8tzXNsDMTk4jSwc1wGySiXUNmZoNXIxQpKSdebGsN2sYxV1dTgXbe9TGl1Lmy0lG/NzR/gmFC/sgnpmA==","_resolved":"/private/var/folders/vd/vvmzq4kn6vq7qwcgg92p1dnh0000gn/T/d2c638cbf6a585d171910e7d5a371ed4/emergence-engineering-prosemirror-who-wrote-what-0.2.0.tgz","_from":"file:emergence-engineering-prosemirror-who-wrote-what-0.2.0.tgz","_nodeVersion":"24.11.1","_npmVersion":"11.6.4","dist":{"integrity":"sha512-B3Y1jD8tzXNsDMTk4jSwc1wGySiXUNmZoNXIxQpKSdebGsN2sYxV1dTgXbe9TGl1Lmy0lG/NzR/gmFC/sgnpmA==","shasum":"bfffec118d103c8ab2d9ebe010af0319cd9dbef4","tarball":"https://registry.npmjs.org/@emergence-engineering/prosemirror-who-wrote-what/-/prosemirror-who-wrote-what-0.2.0.tgz","fileCount":14,"unpackedSize":20773,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIC7pBT4fflKJsbTB/Jvc/JX533Vo1ZzecvFLpYvh4qCRAiEA3tILJRq7fMG6vzsvm2mhEdxMQ9soicUKuT3COS4FXlo="}]},"_npmUser":{"name":"tg44","email":"torcsvari.gergo@gmail.com"},"directories":{},"maintainers":[{"name":"matejcsok","email":"istvan.matejcsok@emergence-engineering.com"},{"name":"viktorvacziee","email":"viktor.vaczi@emergence-engineering.com"},{"name":"tg44","email":"torcsvari.gergo@gmail.com"},{"name":"cskata","email":"katalin.csillag@emergence-engineering.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/prosemirror-who-wrote-what_0.2.0_1776692039159_0.31905722938854497"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-09T08:15:44.405Z","modified":"2026-04-20T13:33:59.478Z","0.1.0":"2026-03-09T08:15:44.692Z","0.1.1":"2026-03-26T13:03:24.415Z","0.2.0":"2026-04-20T13:33:59.292Z"},"bugs":{"url":"https://github.com/emergence-engineering/emergence-tools/issues"},"author":{"name":"Emergence Engineering"},"license":"ISC","homepage":"https://github.com/emergence-engineering/emergence-tools/tree/main/packages/prosemirror-who-wrote-what#readme","keywords":["ProseMirror","Yjs","collaboration","authorship","decorations"],"repository":{"type":"git","url":"git+https://github.com/emergence-engineering/emergence-tools.git","directory":"packages/prosemirror-who-wrote-what"},"description":"Track text authorship in collaborative ProseMirror editors using Yjs — highlights which user wrote which text with colored inline decorations","maintainers":[{"name":"matejcsok","email":"istvan.matejcsok@emergence-engineering.com"},{"name":"viktorvacziee","email":"viktor.vaczi@emergence-engineering.com"},{"name":"tg44","email":"torcsvari.gergo@gmail.com"},{"name":"cskata","email":"katalin.csillag@emergence-engineering.com"}],"readme":"# @emergence-engineering/prosemirror-who-wrote-what\n\n[![logo](https://emergence-engineering.com/ee-logo.svg)](https://emergence-engineering.com)\n\n[**Made by Emergence Engineering**](https://emergence-engineering.com/)\n\nSponsored by [<img src=\"https://lex.page/apple-touch-icon.png\" alt=\"Lex\" width=\"16\" height=\"16\" style=\"vertical-align: middle;\" /> **Lex**](https://lex.page) & **Nathan Baschez**\n\n> Track text authorship in collaborative ProseMirror editors using Yjs. Highlights which user wrote which text with colored inline decorations.\n\n## Features\n\n- Colored inline decorations showing who wrote what\n- Automatic Yjs clientID-to-userId mapping via shared YMap\n- Adaptive debounce that scales with document size\n- Customizable color palette and decoration factory\n- Toggle visibility on/off at runtime\n- Works with any ProseMirror schema — no schema changes needed\n\n## Installation\n\n```bash\nnpm install @emergence-engineering/prosemirror-who-wrote-what\n```\n\n### Peer dependencies\n\n```bash\nnpm install prosemirror-state prosemirror-view yjs y-prosemirror\n```\n\n## Quick Start\n\n```ts\nimport { EditorState } from \"prosemirror-state\";\nimport { EditorView } from \"prosemirror-view\";\nimport { ySyncPlugin } from \"y-prosemirror\";\nimport * as Y from \"yjs\";\nimport {\n  createWhoWroteWhatPlugin,\n  setWhoWroteWhatVisibility,\n} from \"@emergence-engineering/prosemirror-who-wrote-what\";\n\nconst ydoc = new Y.Doc();\nconst yXmlFragment = ydoc.getXmlFragment(\"default\");\n\nconst view = new EditorView(document.getElementById(\"editor\")!, {\n  state: EditorState.create({\n    plugins: [\n      ySyncPlugin(yXmlFragment),\n      createWhoWroteWhatPlugin({ userId: \"alice\" }),\n    ],\n  }),\n});\n\n// Toggle authorship highlighting on/off\nsetWhoWroteWhatVisibility(view, false);\nsetWhoWroteWhatVisibility(view, true);\n```\n\n## Options\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `colors` | `string[]` | 16 built-in colors | Color palette for author highlights. Cycles through sequentially. |\n| `userMapKey` | `string` | `\"userMap\"` | Key for the shared YMap storing clientID-to-userId mappings. |\n| `startVisible` | `boolean` | `true` | Whether decorations are visible when the plugin initializes. |\n| `debounceFactor` | `number` | `1.5` | Multiplier for adaptive debounce. Debounce delay = lastComputeMs * debounceFactor. Set to `0` to disable. |\n| `createDecoration` | `(from, to, color, userId) => Decoration` | inline with `background-color` | Custom decoration factory for full control over how authorship is displayed. |\n\n## API\n\n| Export | Type | Description |\n|--------|------|-------------|\n| `createWhoWroteWhatPlugin` | `(options: WhoWroteWhatOptions) => Plugin` | Creates the authorship tracking plugin. |\n| `setWhoWroteWhatVisibility` | `(view: EditorView, visible: boolean) => void` | Toggles decoration visibility at runtime. |\n| `whoWroteWhatPluginKey` | `PluginKey` | Plugin key for reading plugin state. |\n| `DEFAULT_COLORS` | `string[]` | The 16 built-in pastel colors. |\n| `createColorAssigner` | `(colors: string[]) => (userId) => string` | Creates a function that assigns colors to user IDs. |\n| `WhoWroteWhatMetaType` | `enum` | Meta transaction types (`SetVisibility`). |\n\n## How It Works\n\n1. The plugin observes the Yjs XML fragment and user map for changes.\n2. On each change, it writes the current user's `clientID -> userId` mapping to a shared YMap.\n3. It walks the Yjs document tree, resolves each text item's author via the user map, and creates colored inline decorations.\n4. Decorations are dispatched to the ProseMirror plugin state and rendered by the editor.\n5. An adaptive debounce mechanism scales the recomputation delay with document complexity to keep the editor responsive.\n\n## TipTap\n\nRegister the plugin via TipTap's extension API:\n\n```ts\nimport { Extension } from \"@tiptap/core\";\nimport { createWhoWroteWhatPlugin } from \"@emergence-engineering/prosemirror-who-wrote-what\";\n\nconst WhoWroteWhat = Extension.create({\n  name: \"whoWroteWhat\",\n  addProseMirrorPlugins() {\n    return [createWhoWroteWhatPlugin({ userId: \"current-user\" })];\n  },\n});\n```\n\n## Playground\n\nSee the [interactive demo](https://emergence-engineering.github.io/emergence-tools/#whoWroteWhat) in the monorepo playground.\n\n## License\n\nMIT\n","readmeFilename":"README.md"}