ueberdosis / tiptap Goto Github PK
View Code? Open in Web Editor NEWThe headless rich text editor framework for web artisans.
Home Page: https://tiptap.dev
License: MIT License
The headless rich text editor framework for web artisans.
Home Page: https://tiptap.dev
License: MIT License
The browser return SSL_ERROR_RX_RECORD_TOO_LONG when accessing the website https://tiptap.scrumpy.io !
It is happening on Firefox.
Thanks
I thinking of moving all extensions from tiptap-extension
to its own package. I think every implementation of a rich text editor is extremely individual so a user should only load needed extensions. I know there are features like tree-shaking but related to #16 it seems hard to configure for some users (me too 😅).
So instead of importing all extensions from tiptap-extensions
import {
BlockquoteNode,
BulletListNode,
HardBreakNode,
HeadingNode,
} from 'tiptap-extensions'
we could import extensions like this
import BlockquoteNode from 'tiptap-bockquote-extension'
import BulletListNode from 'tiptap-bulletlist-extension'
import HardBreakNode from 'tiptap-hardbreak-extension'
import HeadingNode from 'tiptap-heading-extension'
Also scoped packages are becoming more and more popular. I'm not sure about its features/caveats but maybe it is something we could think about.
import BlockquoteNode from '@tiptap/bockquote-extension'
import BulletListNode from '@tiptap/bulletlist-extension'
import HardBreakNode from '@tiptap/hardbreak-extension'
import HeadingNode from '@tiptap/heading-extension'
Any thoughts about this? 🤔
Everyone needs @mentions
, #tags
and /commands
. This should be possible with one extension. Rendering should be outside of tiptap.
Hi there. Great job already! Thank you guys.
Would really love to see an example of how to pass a prop to a custom extension.
for example i copied your TodoItem
-extension and tried to pass an object in like this:
<ul data-type="todo_list">
<li
:custom-prop="customProp"
data-type="todo_item"
data-done="true">
Buy beer
</li>
</ul>
and then tried to use this custom-prop inside of the template logic of TodoItem
, but it wasn't available there.
is there a way to achive something like this? an example-code for this in the doc would help not only me, but also other.
Nice component, but this component needs some more testing on mobile devices I think.
At least on iOS, the Menu Bubble sample does not work -> when you select something on iOS there is a native popup already hiding the Menu Bubble.
it would be great to have something similar to this.$refs.editor.clearContent()
that we can use to replace doc dynamically. eg. this.$refs.editor.replaceDoc(doc)
I'm not sure if this is a bug, or if I'm missing something but I would love some help if anyone else has any ideas what might resolve it.
I'm trying to use the tiptap rich text editor with my vue app. I need to be able to copy and paste from a word document into the editor.
For some reason, when I try to copy and paste from my word document into my instance of the tiptap editor, it won't paste anything with the normal paste command. However, if I paste the same thing into one of the examples on https://tiptap.scrumpy.io/, it pastes just fine. I can get it to paste in my instance if I use the "Paste and match style" option on my Mac, but I can't for the life of me figure out why the normal paste command won't work properly for me.
I wasn't sure if there was something strange with my app environment, so I created a brand new vue cli instance and pasted the code straight from https://github.com/heyscrumpy/tiptap/blob/master/examples/Components/Routes/Basic/index.vue into it. I installed tiptap & tiptap-extensions. It still wouldn't let me copy and paste from a word document with the normal paste command.
I pulled down the tiptap repo and ran that, and it works properly there, so I'm wondering if there's some dependency or setting I'm not aware that I need to have setup?
Any suggestions as to what might be causing the problem would be greatly appreciated.
Potentially stupid question but this has left me stumped...
I've tried dropping tiptap into a vue app and if I try to include a menu bar I get the following error:
[Vue warn]: Error in nextTick: "TypeError: invalid 'instanceof' operand type"
This is when using the menu example from the readme. Any suggestions or pointers would be really appreciated. I'm using the latest version of vue.
Thanks
Hi,
Thanks for this great library! Quick question/issue below.
Links on demo site are not clickable under the Links demo. Is this intentional? Part of the editing mode? I tried in a local test example, and same effect.
Thanks
Steve
Me again! Is there any way to support placeholder text within the editor that clears when the editor is focused?
It would be nice to implement highlight.js or prism.js (or something else?) for syntax highlighting. Maybe this is possible through prosemirror decorations?
Is there a way, to directly edit html source code? I mean, is there a way, to add a button to toggle wysiwyg view to source-code view?
I've attempted to launch Tiptap on my workstation according to development setup, but on Windows 10 it's showing error message while I'm trying to do "yarn start".
I did a PR with fix if someone experiencing same issues. #42
(Also, I'm new to all this open-source thing, so any recommendations would be appreciated)
The Menu Bubble is currently incompatible with Android Pie, as selecting the text brings up a magnifier, and letting go brings up the Android selection context menu.
Perhaps when viewed in mobile, the Menu Bubble can display /below/ the highlighted text rather than above so that users can still interact with it.
Hello, great plugin with great extensibility.
I would like to ask, is there a way (hint) how to implement an extension for making buttons for font size and family, font colors would be great too.
I could not find a solution from prosemirror and i suppose this project inherits this issue too?
Hi
I've checkout the current code base and I am running
npm install
and npm start
However, I am getting a series of errors like this:
ERROR in ./packages/tiptap-commands/src/index.js Module not found: Error: Can't resolve 'prosemirror-commands' in '/Users/pedro/Projects/tiptap-master/packages/tiptap-commands/src' @ ./packages/tiptap-commands/src/index.js 1:0-369 9:0-13:69 9:0-13:69 9:0-13:69 9:0-13:69 9:0-13:69 9:0-13:69 9:0-13:69 9:0-13:69 9:0
What's the correct way of building and running locally?
Thank you
In my use case, I can only load and save Markdown. It is similar to the Prosemirror Markdown example, but instead of the Prosemirror editor I want to use TipTap.
What’s the best way to integrate the Prosemirror Markdown package into TipTap?
I'm using tiptap within a messaging service and would like to clear the contents of the editor when a message is uploaded. However, I can't quite work out how I would go about doing this.
Once again, looking for a little bit of assistance with this, please. 👍
I think this is a nice way to get attention from developers willing to contribute (even a little) with this project.
This is a list of features I would love to see in the first major version of tiptap. (WIP)
Overhaul components
Replace scoped slots with components (see #20). Add <editor />
, <editor-menubar />
and <editor-menububble />
components. Implementing separated components lets us nest markup more easier.
Improve commands
Currently you can only register one command per extension (see #44). Sometimes this is limiting. For example, it would be nice to register an undo and redo command in the HistoryExtension. It would make sense to rename command
to commands
.
Better support for Tree-Shaking (see #16)
Unit tests + coverage
A minimum of unit test + coverage should be part of this release.
Setup a CI server (e.g. Travis)
I am open to further suggestions 🙌
Hey, firstly thanks for such an awesome editor. Love it!
However, I cannot seem to get any of the built in extensions to actually run. I've got an instance setup with a simple editor and the same code as the hidden menubar example but when I click to edit the code (bold, for example) the menubar disappears but nothing happens to the code. Calling the update method to grab the built html returns code without the additional formatting.
Any pointers?
Hi,
I want to insert a image to the editor, i found setContent
in this link (https://tiptap.scrumpy.io/export) but this code will replace all the text on my editor. Is there another function to append the image to the editor?
Thanks in advance.
Having the cursor placed in "test" and clicking on the unordered-list
| odered-list
icon results in a RangeError:
Menu buttons are implemented like in the base-example
Inserting a list manually and then clicking on one of the list icons works. Clicking again results in the error mentioned above.
I can't replicate the error in your implementation example, any idea on how to solve this?
p.s. thanks a lot for the editor :) was looking for such a tool for a long time!
After v0.16.0, I cannot insert new line at the line end by pressing enter key.
If pressing enter key at the middle of the line, the line break still able to insert.
I tested v0.15.0 line breaks can still be inserted in this version.
It look like "tiptap-extensions" is load all extensions even i did not use all of them.
import {
BlockquoteNode,
BulletListNode,
HardBreakNode,
HeadingNode,
ImageNode,
ListItemNode,
OrderedListNode,
BoldMark,
ItalicMark,
HistoryExtension,
} from 'tiptap-extensions'
I use only these extensions but in my vendor file, there is "highlight.js" dependency.
It would be nice if we can import only what we use.
Hi,
Loving the package so far! Was all going swimmingly until we hit a bit of a complication.
We've provided a list of Mentionables
to the component, which are sources from various locations, e.g Admins, Authors, Doctors, Nurses etc.
We provide the object similar to
[{
"id": 1,
"label": "Some name",
"type": "Admin"
}]
--
Our backend needs to know the type of Mentionable so it can locate them from the correct data source to setup notifications etc - however when we get the final HTML it looks something like
"<p><span class="mention" data-mention-id="4">@Mr Something</span> woo woo</p>"
However it only has the ID and Name - Ideally we want to have something like data-type="Admin"
so our backend can parse the code and know what type of Mentionable this was.
--
How would we go about adding the extra information to the HTML that it returns?
Thanks :)
I'd like to be able to detect if cursor is on an empty line and show a menu where people can use to Add (image, video, iframe, etc...)
Can you help me figure out how to achieve that? I tried to add a plugin but the view()
method is never called:
export default function () {
return new Plugin({
view(editorView) {
return new AddNodes({ editorView })
},
})
}
Currently we're using scoped slots for content and menus.
<editor>
<!-- Content goes here -->
<div slot="content" slot-scope="props">
<p>some text</p>
</div>
<!-- Render menubar -->
<div slot="menubar" slot-scope="{ nodes }">
<div v-if="nodes">
<button @click="nodes.heading.command({ level: 1 })">
H1
</button>
</div>
</div>
<!-- Render menububble -->
<div slot="menububble" slot-scope="{ marks }">
<div v-if="marks">
<button @click="marks.bold.command()">
Bold
</button>
</div>
</div>
</editor>
There are two limitations for doing so:
marks
and nodes
like this <div v-if="marks">
. For one tick these values are null
. It would be nice to render these slots only when these values are available but then we do not have access to the DOM element of this slot which is required for the menububble plugin.Maybe it would be nice to use components like this:
<editor>
<!-- Content goes here -->
<editor-content>
<p>some text</p>
</editor-content>
<!-- Render menubar -->
<editor-menubar>
<template slot-scope="{ nodes }">
<button @click="nodes.heading.command({ level: 1 })">
H1
</button>
</template>
</editor-menubar>
<!-- Render menububble -->
<editor-menububble>
<template slot-scope="{ marks }">
<button @click="marks.bold.command()">
Bold
</button>
</template>
</editor-menububble>
</editor>
But I'm not sure how these components will work together and sync its editor state. With provide
and inject
or an event bus or passing props? 🤷♂️
I have custom Node, Mark in my project, after upgrading to version 0.11.1 the following error will be thrown:
index.js:3296 Uncaught TypeError: this.nodes[node.type.name] is not a function
at DOMSerializer.serializeNode (index.js:3296)
at index.js:3280
at Fragment.forEach (index.js:242)
at DOMSerializer.serializeFragment (index.js:3256)
at DOMSerializer.serializeNode (index.js:3305)
at index.js:3280
at Fragment.forEach (index.js:242)
at DOMSerializer.serializeFragment (index.js:3256)
at VueComponent.getHTML (tiptap.esm.js:773)
at VueComponent.beforeSubmit (index.vue?e4fa:898)
I'm trying to do a setContent function to pre-populate the text the user entered in a "create" phase. This text has markup in it, and the markup is showing in the element as text, rather than formatting the text as I'd like it to. I've not been able to find documentation on how I might get the text to show up as marked-up HTML rather than just text.
My setContent function
setContent() { this.$refs.editor_low.setContent({ type: 'doc', content: [{ type: 'paragraph', content: [ { type: 'text', text: this.form.low_criteria, }, ], }], }); }
Editor code:
<editor :extensions="extensions" @update="onUpdateLowCriteria" ref="editor_low"> <div slot="menubar" slot-scope="{ nodes, marks }"> <div v-if="nodes && marks" class="border-bottom mb-2"> <component-menubar :nodes="nodes" :marks="marks"></component-menubar> </div> </div> <div slot="content" slot-scope="props"></div> </editor>
`
edited because of spam
Currently you can only register one command per extension. Sometimes this is limiting. For example, it would be nice to register an undo and redo command in the HistoryExtension. It would make sense to rename command
to commands
.
I think of an implementation like this:
Register one command with the name of its extension (custom_node
).
export default class CustomNode extends Node {
get name() {
return 'custom_node'
}
commands({ type }) {
return someCommand(type)
}
}
Register one chained command with the name of its extension (custom_node
).
export default class CustomNode extends Node {
get name() {
return 'custom_node'
}
commands({ type }) {
return [
someCommand(type),
anotherCommand(type),
]
}
}
Registering multiple commands (undo
, redo
).
export default class CustomNode extends Node {
get name() {
return 'history'
}
commands() {
return {
'undo': someCommand(),
'redo': [
someCommand(),
anotherCommand(),
],
}
}
}
The following Node generates <p></p>
only from getHTML()
class CenterNode extends Node {
get name() {
return 'center'
}
get schema() {
return {
content: 'inline*',
group: 'block',
defining: true,
draggable: false,
parseDOM: [
{
tag: 'p[align="center"]',
},
],
toDOM: (node) => ['p', { align: 'center' }, 0],
}
}
command({ type, schema, attrs }) {
console.log(type)
return toggleBlockType(type, schema.nodes.paragraph, attrs)
}
}
Hello, I have the following single file component on top of which I drop an image:
`
Test Text
export default {
components: {
'editor': Editor,
},
data() {
return {
extensions: [
new HardBreakNode(),
new HeadingNode({ maxLevel: 3 }),
new ImageNode(),
new BoldMark(),
new CodeMark(),
new ItalicMark(),
]
}
}
`
The dragging and dropping of an image works on firefox , but not on chrome.
On chrome I receive a Resource interpreted as Document but transferred with MIME type image/gif: "file:///home/mihaita/Pictures/giphy.gif".
warning and then the browser proceeds to navigate to the dropped file file:///home/mihaita/Pictures/giphy.gif
;
Any ideas what goes wrong?
I've just cloned the repo, installed all dependencies and ran the examples and got this:
yarn run build:examples
$ ./node_modules/@babel/node/bin/babel-node.js build/examples/build.js --env=production
⠋ Building …(node:27582) DeprecationWarning: Tapable.plugin is deprecated. Use new API on `.hooks` instead
What about making webpack@4
the default for development purposes? I don't think it will break anything for users of the library
I tried implementing with the PlaceholderExtension
like in the example, however a RangeError occurred when trying to access the page with the editor.
Any suggestion what I might do wrong?
The error does not occurr when removing the PlaceholderExtension
Hello, thanks for this great editor library. I made three mark say left, center, and right alignment. When I turn on center align, my text can be inserted at center, when I turn on right align, the text will align to right but center is still on state, is it possible to turn off other marks programatically?
Is there an example to reload the extracted json into the editor? I couldn't find it in the docs.
Hello,
I'm trying to use tiptap as the editor for a personal wiki project, and I'm having trouble getting links to insert. I've copied the code right out of the Links example (and then moved it from menububble to menubar, but this is not the issue), but something deep in prosemirror raises an exception when trying to manipulate the DOM.
Here's my cleaned up source code dumped into a fresh vue-cli environment: https://github.com/wizpig64/vue-wiki-test (see src/components/Editor.vue
and EditorMenubar.vue
)
And a live demo: https://wiki.wizpig64.com/ [[will remove this soon]]
Here's the traceback provided by chrome when trying to add a link:
index.js?703f:1293 Uncaught DOMException: Failed to execute 'insertBefore' on 'Node': This node type does not support this method.
at renderDescs (webpack-internal:///./node_modules/prosemirror-view/dist/index.js:1293:17)
at renderDescs (webpack-internal:///./node_modules/prosemirror-view/dist/index.js:1297:7)
at NodeViewDesc.renderChildren (webpack-internal:///./node_modules/prosemirror-view/dist/index.js:1102:5)
at NodeViewDesc.updateChildren (webpack-internal:///./node_modules/prosemirror-view/dist/index.js:1098:64)
at NodeViewDesc.updateInner (webpack-internal:///./node_modules/prosemirror-view/dist/index.js:1120:33)
at NodeViewDesc.update (webpack-internal:///./node_modules/prosemirror-view/dist/index.js:1112:10)
at ViewTreeUpdater.updateNextNode (webpack-internal:///./node_modules/prosemirror-view/dist/index.js:1498:14)
at eval (webpack-internal:///./node_modules/prosemirror-view/dist/index.js:1087:17)
at iterDeco (webpack-internal:///./node_modules/prosemirror-view/dist/index.js:1573:7)
at NodeViewDesc.updateChildren (webpack-internal:///./node_modules/prosemirror-view/dist/index.js:1072:5)
Edit: In firefox it's a HierarchyRequestError:
HierarchyRequestError: Node cannot be inserted at the specified point in the hierarchy index.js:1293
renderDescs index.js:1293
renderDescs index.js:1297
renderChildren index.js:1102
updateChildren index.js:1098
updateInner index.js:1120
update index.js:1112
updateNextNode index.js:1498
updateChildren/< index.js:1087
iterDeco index.js:1573
updateChildren index.js:1072
updateInner index.js:1120
update index.js:1112
updateState index.js:4250
dispatchTransaction tiptap.esm.js:766
dispatchTransaction self-hosted:987:17 dispatch index.js:4465
dispatch self-hosted:987:17 updateMark/< commands.esm.js:194
commands/</obj[name] tiptap.esm.js:383
setLinkUrl EditorMenubar.vue:108
setLinkUrl self-hosted:991:17 submit EditorMenubar.vue:147
invoker vue.runtime.esm.js:2023
withMacroTask/fn._withTask vue.runtime.esm.js:1822
I don't get the same error when running the Links example, but as a newbie javascript developer, I guess I just don't know what I'm doing wrong at this point.
Thanks for any advice you can give!
Hi,
awesome library!
It would be great if vue
was added to the tiptap
package as a peerDependency
, because it is required in packages/tiptap/src/utils/ComponentView.js
. Tools like Bundlephobia throw an error over this.
Where should I put all my gifs?!? We'll need basic image support.
Hello, I would like to thank you for creating such an awesome Vue component and I would love to use it. However, we need to use typescript and then importing your editor will only cause compile time errors due to missing type definitions. Could I suggest making these available on definitelyTyped?
I am currently looking into solving this myself but as I am neither familiar with your code base nor creating type definitions at this level I thought I should see if someone can help or give pointers.
Hey there,
thanks for this great package. I am right now building a Laravel Nova package for adding your text editor, which comes along nicely.
I have a problem implementing the blockquote node, though - do you have an example implementation?
It seems (it looks this way in the Prosemirror example) there should be a button to decrement the blockquote level. Have you already worked on that and I haven't found it yet?
Thanks again,
Sebastian
I have my own implementation for Image
which renders the image inside a nested <span>
tree
However dragging behaviour seems broken to me, any idea how to fix it? Thanks.
class ImageNode extends Node {
get name() {
return 'image-node'
}
get view() {
return {
props: ['node'],
render(h) {
const { src, width, height } = this.node.attrs
const ratio = (height / width) * 100
return h('span', {
attrs: {
'style': `width: ${width}px;`,
},
domProps: { innerHTML: `<span style="padding-bottom: ${ratio}%;"><img alt src="${src}"></span>` },
})
},
}
}
get schema() {
return {
attrs: {
src: { default: 'http://' },
width: { default: 16 },
height: { default: 16 },
},
inline: true,
group: 'inline',
draggable: true,
parseDOM: [
{
tag: 'span',
getAttrs: (dom) => ({
src: dom.getAttribute('data-src'),
width: dom.getAttribute('data-width'),
height: dom.getAttribute('data-height'),
}),
},
],
toDOM: ({ attrs: { src, width, height } }) => ['span', {
'data-src': src,
'data-width': width,
'data-height': height,
}],
}
}
command({ type, attrs }) {
return (state, dispatch) => {
const { $from } = state.selection
if (!$from.parent.canReplaceWith($from.index(), $from.index(), type)) {
return
}
dispatch(state.tr.replaceSelectionWith(type.create(attrs)))
}
}
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.