{"id":13532431,"url":"https://github.com/andi23rosca/tiptap-solid","last_synced_at":"2025-04-14T22:54:34.625Z","repository":{"id":126106352,"uuid":"419431398","full_name":"andi23rosca/tiptap-solid","owner":"andi23rosca","description":null,"archived":false,"fork":false,"pushed_at":"2024-07-25T11:06:27.000Z","size":172,"stargazers_count":48,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-14T22:54:19.208Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/andi23rosca.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-10-20T17:42:41.000Z","updated_at":"2025-02-20T14:04:28.000Z","dependencies_parsed_at":"2024-03-27T13:43:58.124Z","dependency_job_id":"5a63d04a-5a78-4918-b018-d116f7c787b4","html_url":"https://github.com/andi23rosca/tiptap-solid","commit_stats":{"total_commits":16,"total_committers":2,"mean_commits":8.0,"dds":0.0625,"last_synced_commit":"9048fb7d7d03fb464759b1d04eed4548a3b8b727"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andi23rosca%2Ftiptap-solid","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andi23rosca%2Ftiptap-solid/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andi23rosca%2Ftiptap-solid/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andi23rosca%2Ftiptap-solid/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/andi23rosca","download_url":"https://codeload.github.com/andi23rosca/tiptap-solid/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248975330,"owners_count":21192208,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T07:01:10.904Z","updated_at":"2025-04-14T22:54:34.600Z","avatar_url":"https://github.com/andi23rosca.png","language":"TypeScript","funding_links":[],"categories":["📦 Components \u0026 Libraries","TypeScript"],"sub_categories":["Form"],"readme":"# tiptap-solid\n\n\u003e Solid components for tiptap v2\n\n[![Open in Visual Studio Code](https://img.shields.io/static/v1?logo=visualstudiocode\u0026label=\u0026message=Open%20in%20VS%20Code\u0026labelColor=2c2c32\u0026color=007acc\u0026logoColor=007acc)](https://open.vscode.dev/andi23rosca/tiptap-solid)\n[![NPM Version](https://badgen.net/npm/v/tiptap-solid)](https://www.npmjs.com/package/tiptap-solid)\n[![Total Downloads](https://badgen.net/npm/dt/tiptap-solid)](https://www.npmjs.com/package/tiptap-solid)\n[![Monthly Downloads](https://badgen.net/npm/dm/tiptap-solid)](https://www.npmjs.com/package/tiptap-solid)\n[![License](https://badgen.net/npm/license/tiptap-solid)](https://github.com/andi23rosca/tiptap-solid/blob/master/LICENSE)\n\n## Installation\n\n```bash\nnpm i tiptap-solid\n\n# or\n\nyarn add tiptap-solid\n```\n\n**Note**: This package just provides components for solid. For configuring/customizing the editor, refer [tiptap's official documentation](https://www.tiptap.dev/).\n\nFor any issues with the editor. You may need to open the issue on [tiptap's repository](https://github.com/ueberdosis/tiptap/issues)\n\n## Issues\nThere's a recurring issue caused by prosemirror dependencies: `RangeError: Adding different instances of a keyed plugin (plugin$)`\nThese are the steps to fix it:\n1. add all `prosemirror` dependencies explicityly: `yarn add prosemirror-state prosemirror-transform prosemirror-model prosemirror-view`\n2. include the packages in `vite.config.ts` in `optimizeDeps`\n```ts\n  optimizeDeps: {\n    include: [\n      'prosemirror-state',\n      'prosemirror-transform',\n      'prosemirror-model',\n      'prosemirror-view'\n    ]\n  }\n```\n\n## Usage\nThe structure of the helper components has been designed to mimic the React components provided by tiptap, so for further inspiration on how to use `tiptap-solid` see [tiptap's section on React](https://tiptap.dev/guide/node-views/react)\n\n### A Simple editor\n\n```tsx\nimport { Component } from \"solid-js\";\nimport StarterKit from \"@tiptap/starter-kit\";\nimport { createEditor, EditorContent } from \"tiptap-solid\";\n\nconst App: Component = () =\u003e {\n  const editor = createEditor({\n    extensions: [StarterKit],\n    content: `Hello world!`,\n  });\n  return \u003cEditorContent editor={editor()} /\u003e;\n};\n```\n\n### Rendering a Solid component inside the editor:\n\n#### Create a component `Counter.tsx`\n```tsx\nimport { NodeViewProps } from \"@tiptap/core\";\nimport { Component } from \"solid-js\";\nimport { NodeViewWrapper, NodeViewContent } from \"tiptap-solid\";\n\nconst Counter: Component\u003cNodeViewProps\u003e = (props) =\u003e {\n  const increase = () =\u003e {\n    props.updateAttributes({\n      count: props.node.attrs.count + 1,\n    });\n  };\n\n  return (\n    \u003cNodeViewWrapper className=\"solid-component\"\u003e\n      \u003cspan contenteditable={false} className=\"label\"\u003e\n        Solid Component\n      \u003c/span\u003e\n\n      \u003cdiv contenteditable={false} className=\"content\"\u003e\n        \u003cbutton onClick={increase}\u003e\n          This button has been clicked {props.node.attrs.count} times.\n        \u003c/button\u003e\n      \u003c/div\u003e\n\n      \u003cNodeViewContent /\u003e\n    \u003c/NodeViewWrapper\u003e\n  );\n};\nexport default Counter;\n```\n\n#### Create a node extension `Extension.ts`\n\n```ts\nimport { Node, mergeAttributes } from \"@tiptap/core\";\nimport { SolidNodeViewRenderer } from \"tiptap-solid\";\nimport Counter from \"./Counter\";\n\nexport default Node.create({\n  name: \"solidComponent\",\n  group: \"block\",\n  content: 'inline*',\n  addAttributes() {\n    return {\n      count: {\n        default: 0,\n      },\n    };\n  },\n  parseHTML() {\n    return [\n      {\n        tag: \"solid-component\",\n      },\n    ];\n  },\n  renderHTML({ HTMLAttributes }) {\n    return [\"solid-component\", mergeAttributes(HTMLAttributes)];\n  },\n  addNodeView() {\n    return SolidNodeViewRenderer(Counter);\n  },\n});\n```\n\n#### Register extension in your editor, and use the component's tag `App.tsx`\n```tsx\nimport { Component } from \"solid-js\";\nimport StarterKit from \"@tiptap/starter-kit\";\nimport { createEditor, EditorContent } from \"tiptap-solid\";\nimport Extension from \"./Extension\";\n\nconst App: Component = () =\u003e {\n  const editor = createEditor({\n    extensions: [StarterKit, Extension],\n    content: `\n    \u003cp\u003e\n      This is still the text editor you’re used to, but enriched with node views.\n    \u003c/p\u003e\n\n    \u003csolid-component count=\"5\"\u003e\n      \u003cp\u003e\n        Editable\n      \u003c/p\u003e\n    \u003c/solid-component\u003e\n    \n    \u003cp\u003e\n      Did you see that? That’s a Solid component. We are really living in the future.\n    \u003c/p\u003e\n    `,\n  });\n\n  return \u003cEditorContent editor={editor()} /\u003e;\n};\n```\n## Solid Contexts\n`solid` works with the concept of reactivity owners. Any `createEffect`, `useContext`, etc. is tied to the owner it's defined in.\n\nOwners can have children and parents similarly to how components have children and parents, when you try to use a context. \nSolid will look up the chain of reactivity owners for the closest one that has the context.\n\nThe custom node components in `tiptap-solid` are rendered somewhat independently, but the library has some internal logic that automatically attaches the owner of `EditorContent` to any node components rendered inside of it.\n\nThe issue is if you need to use contexts inside of the extensions classes. The classes are instantiated and called outside of the usual reactivity tree, and don't have access to any of the contexts.\n\nAs a workaround the library exports a function called `getTiptapSolidReactiveOwner` that will return the owner of the `EditorContent` component.\nUsing the return with `runWithOwner` will let you have access to any context editor has access to.\n\nExample: \n```ts\nexport default Node.create({\n  name: \"solidComponent\",\n  group: \"block\",\n  atom: true,\n  addAttributes() {\n    return {\n      count: {\n        default: 0,\n      },\n    };\n  },\n  parseHTML() {\n    return [\n      {\n        tag: \"solid-component\",\n      },\n    ];\n  },\n  renderHTML({ HTMLAttributes }) {\n    const owner = getTiptapSolidReactiveOwner(this.editor);\n    const context = runWithOwner(owner, () =\u003e useContext(SomeContext));\n    // Do some logic based on the context, render stuff differently, etc.\n    return [\"solid-component\", mergeAttributes(HTMLAttributes)];\n  },\n  addNodeView() {\n    return SolidNodeViewRenderer(Counter);\n  },\n});\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandi23rosca%2Ftiptap-solid","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fandi23rosca%2Ftiptap-solid","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandi23rosca%2Ftiptap-solid/lists"}