diff --git a/examples/Components/Routes/Placeholder/index.vue b/examples/Components/Routes/Placeholder/index.vue
new file mode 100644
index 00000000..217e68b5
--- /dev/null
+++ b/examples/Components/Routes/Placeholder/index.vue
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
diff --git a/examples/Components/Subnavigation/index.vue b/examples/Components/Subnavigation/index.vue
index fb743d9b..1297a4de 100644
--- a/examples/Components/Subnavigation/index.vue
+++ b/examples/Components/Subnavigation/index.vue
@@ -30,6 +30,9 @@
Embeds
+
+ Placeholder
+
Export HTML or JSON
diff --git a/examples/main.js b/examples/main.js
index d25aaf9b..0ac47f0d 100644
--- a/examples/main.js
+++ b/examples/main.js
@@ -13,6 +13,7 @@ import RouteMarkdownShortcuts from 'Components/Routes/MarkdownShortcuts'
import RouteCodeHighlighting from 'Components/Routes/CodeHighlighting'
import RouteReadOnly from 'Components/Routes/ReadOnly'
import RouteEmbeds from 'Components/Routes/Embeds'
+import RoutePlaceholder from 'Components/Routes/Placeholder'
import RouteExport from 'Components/Routes/Export'
const __svg__ = { path: './assets/images/icons/*.svg', name: 'assets/images/[hash].sprite.svg' }
@@ -93,6 +94,13 @@ const routes = [
githubUrl: 'https://github.com/heyscrumpy/tiptap/tree/master/examples/Components/Routes/Embeds',
},
},
+ {
+ path: '/placeholder',
+ component: RoutePlaceholder,
+ meta: {
+ githubUrl: 'https://github.com/heyscrumpy/tiptap/tree/master/examples/Components/Routes/Placeholder',
+ },
+ },
{
path: '/export',
component: RouteExport,
diff --git a/packages/tiptap-extensions/package.json b/packages/tiptap-extensions/package.json
index 95d5120e..5ac6a811 100644
--- a/packages/tiptap-extensions/package.json
+++ b/packages/tiptap-extensions/package.json
@@ -22,6 +22,7 @@
"dependencies": {
"lowlight": "^1.10.0",
"prosemirror-history": "^1.0.2",
+ "prosemirror-view": "^1.5.1",
"tiptap": "^0.10.0",
"tiptap-commands": "^0.3.0"
}
diff --git a/packages/tiptap-extensions/src/extensions/Placeholder.js b/packages/tiptap-extensions/src/extensions/Placeholder.js
new file mode 100644
index 00000000..a0a659ff
--- /dev/null
+++ b/packages/tiptap-extensions/src/extensions/Placeholder.js
@@ -0,0 +1,39 @@
+import { Extension, Plugin } from 'tiptap'
+import { Decoration, DecorationSet } from 'prosemirror-view'
+
+export default class PlaceholderExtension extends Extension {
+
+ get name() {
+ return 'placeholder'
+ }
+
+ get defaultOptions() {
+ return {
+ emptyNodeClass: 'is-empty',
+ }
+ }
+
+ get plugins() {
+ return [
+ new Plugin({
+ props: {
+ decorations: state => {
+ const decorations = []
+
+ state.doc.descendants((node, pos) => {
+ if (node.type.isBlock && node.childCount === 0) {
+ const decoration = Decoration.node(pos, pos + node.nodeSize, {
+ class: this.options.emptyNodeClass,
+ })
+ decorations.push(decoration)
+ }
+ })
+
+ return DecorationSet.create(state.doc, decorations)
+ },
+ },
+ }),
+ ]
+ }
+
+}
diff --git a/packages/tiptap-extensions/src/index.js b/packages/tiptap-extensions/src/index.js
index 3aa41036..d40b75ed 100644
--- a/packages/tiptap-extensions/src/index.js
+++ b/packages/tiptap-extensions/src/index.js
@@ -17,3 +17,4 @@ export { default as LinkMark } from './marks/Link'
export { default as StrikeMark } from './marks/Strike'
export { default as HistoryExtension } from './extensions/History'
+export { default as PlaceholderExtension } from './extensions/Placeholder'
diff --git a/yarn.lock b/yarn.lock
index ea82c0a8..3485070e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7791,7 +7791,7 @@ prosemirror-utils@^0.6.5:
version "0.6.5"
resolved "https://registry.yarnpkg.com/prosemirror-utils/-/prosemirror-utils-0.6.5.tgz#df18e39178d510917838a7337a8b64561324a70b"
-prosemirror-view@^1.0.0, prosemirror-view@^1.4.3:
+prosemirror-view@^1.0.0, prosemirror-view@^1.4.3, prosemirror-view@^1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.5.1.tgz#545176a65124a89c9d16571797a9ef54853628c4"
dependencies: