mirror of
https://github.com/tenrok/vue-tribute.git
synced 2026-05-17 05:49:38 +03:00
Initial commit
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
# vue-prosemirror
|
||||
# vue-input-autosize
|
||||
|
||||
> A simple Vue.js wrapper around the ProseMirror editor
|
||||
> A simple Vue.js directive for autosizing a text input based on its content.
|
||||
|
||||
## Install
|
||||
|
||||
```js
|
||||
$ npm install vue-prosemirror --save
|
||||
$ npm install vue-input-autosize --save
|
||||
```
|
||||
|
||||
## Usage
|
||||
@@ -19,4 +19,4 @@ Coming soon...
|
||||
## TODO
|
||||
|
||||
- [ ] Tests
|
||||
- [ ] Tidy up example
|
||||
- [ ] Improve the example
|
||||
|
||||
+9
-28
@@ -1,40 +1,21 @@
|
||||
<template>
|
||||
<textarea @keyup="syncToEditor">{{ editorDisplayVal }}</textarea>
|
||||
<prosemirror :content="editorVal" :on-change="editorChanged" menu-type="tooltip"></prosemirror>
|
||||
<input type="text" v-input-autosize v-model="foo" placeholder="Butts" />
|
||||
</template>
|
||||
<script>
|
||||
import VueProseMirror from "../";
|
||||
import Vue from "vue";
|
||||
import VueInputAutosize from "../";
|
||||
|
||||
Vue.use(VueInputAutosize);
|
||||
|
||||
export default {
|
||||
name: "app",
|
||||
data(){
|
||||
return {
|
||||
editorVal: "",
|
||||
editorDisplayVal: ""
|
||||
}
|
||||
},
|
||||
ready(){
|
||||
console.log("Ready!")
|
||||
},
|
||||
methods: {
|
||||
editorChanged(raw, rendered){
|
||||
this.editorDisplayVal = raw;
|
||||
console.log(rendered)
|
||||
},
|
||||
syncToEditor($event){
|
||||
this.editorVal = $event.target.value;
|
||||
data(){
|
||||
return {
|
||||
foo: "Hello"
|
||||
}
|
||||
},
|
||||
components: {
|
||||
prosemirror: VueProseMirror
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.vueProseMirror .ProseMirror .ProseMirror-content{
|
||||
width: 500px;
|
||||
margin: 50px auto;
|
||||
border: 1px solid #eee;
|
||||
outline: none;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,81 +1,55 @@
|
||||
'use strict';
|
||||
|
||||
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
|
||||
exports.install = function (Vue, options) {
|
||||
Vue.directive("input-autosize", {
|
||||
mirror: null,
|
||||
val: " ",
|
||||
options: {},
|
||||
bind: function bind() {
|
||||
var _this = this;
|
||||
|
||||
var prosemirror = _interopDefault(require('prosemirror'));
|
||||
var prosemirror_dist_schemaBasic = require('prosemirror/dist/schema-basic');
|
||||
var prosemirror_dist_markdown = require('prosemirror/dist/markdown');
|
||||
var prosemirror_dist_exampleSetup = require('prosemirror/dist/example-setup');
|
||||
var prosemirror_dist_menu = require('prosemirror/dist/menu');
|
||||
var defaults = { maxWidth: 500, minWidth: 20, comfortZone: 0 };
|
||||
this.options = Object.assign(defaults, options || {});
|
||||
|
||||
var index = { template: "<div class=vueProseMirror></div>",
|
||||
name: "ProseMirror",
|
||||
props: {
|
||||
content: String,
|
||||
onChange: Function,
|
||||
menuType: {
|
||||
type: String,
|
||||
default: "bar"
|
||||
this.mirror = document.createElement("span");
|
||||
this.mirror.classList.add("vue-input-autosize-mirror");
|
||||
document.body.appendChild(this.mirror);
|
||||
|
||||
this.el.addEventListener("input", this.check.bind(this, this.el), false);
|
||||
setTimeout(function () {
|
||||
var styles = window.getComputedStyle(_this.el, null);
|
||||
Object.assign(_this.mirror.style, {
|
||||
position: "absolute",
|
||||
top: "-9999px",
|
||||
left: "-9999px",
|
||||
width: "auto",
|
||||
whiteSpace: "nowrap",
|
||||
fontSize: styles.getPropertyValue("font-size"),
|
||||
fontFamily: styles.getPropertyValue("font-family"),
|
||||
fontWeight: styles.getPropertyValue("font-weight"),
|
||||
letterSpacing: styles.getPropertyValue("letter-spacing"),
|
||||
textTransform: styles.getPropertyValue("text-transform"),
|
||||
ariaHidden: true
|
||||
});
|
||||
_this.check(_this.el);
|
||||
}, 0);
|
||||
},
|
||||
options: Object
|
||||
},
|
||||
data: function data() {
|
||||
return {
|
||||
editor: null
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
rawMarkdown: function rawMarkdown() {
|
||||
return prosemirror_dist_markdown.defaultMarkdownSerializer.serialize(this.editor.doc);
|
||||
update: function update() {
|
||||
this.check(this.el);
|
||||
},
|
||||
renderedContent: function renderedContent() {
|
||||
var docFrag = this.editor.doc.content.toDOM();
|
||||
var div = document.createElement("div");
|
||||
div.appendChild(docFrag.cloneNode(true));
|
||||
return div.innerHTML;
|
||||
}
|
||||
},
|
||||
ready: function ready() {
|
||||
var _this = this;
|
||||
|
||||
var editorOptions = Object.assign({
|
||||
schema: prosemirror_dist_schemaBasic.schema,
|
||||
place: this.el,
|
||||
doc: prosemirror_dist_markdown.defaultMarkdownParser.parse(this.content),
|
||||
plugins: [prosemirror_dist_exampleSetup.exampleSetup.config({ menuBar: false, tooltipMenu: false })]
|
||||
}, this.options);
|
||||
|
||||
if (editorOptions.doc === undefined || editorOptions.doc === null) {
|
||||
editorOptions.doc = null;
|
||||
editorOptions.docFormat = null;
|
||||
}
|
||||
|
||||
this.editor = new prosemirror.ProseMirror(editorOptions);
|
||||
|
||||
var menu = prosemirror_dist_exampleSetup.buildMenuItems(prosemirror_dist_schemaBasic.schema);
|
||||
if (this.menuType === "bar") {
|
||||
prosemirror_dist_menu.tooltipMenu.detach(this.editor);
|
||||
prosemirror_dist_menu.menuBar.config({ float: true, content: menu.fullMenu }).attach(this.editor);
|
||||
} else {
|
||||
prosemirror_dist_menu.menuBar.detach(this.editor);
|
||||
prosemirror_dist_menu.tooltipMenu.config({
|
||||
selectedBlockMenu: true,
|
||||
inlineContent: menu.inlineMenu,
|
||||
blockContent: menu.blockMenu
|
||||
}).attach(this.editor);
|
||||
}
|
||||
|
||||
this.editor.on.change.add(function () {
|
||||
if (_this.onChange && typeof _this.onChange === "function") {
|
||||
_this.onChange.apply(null, [_this.rawMarkdown, _this.renderedContent]);
|
||||
check: function check(el) {
|
||||
this.val = el.value;
|
||||
if (!this.val) this.val = el.placeholder || "";
|
||||
this.mirror.innerHTML = this.val.replace(/&/g, "&").replace(/\s/g, " ").replace(/</g, "<").replace(/>/g, ">");
|
||||
var newWidth = this.mirror.getBoundingClientRect().width + this.options.comfortZone;
|
||||
if (newWidth > this.options.maxWidth) {
|
||||
newWidth = this.options.maxWidth;
|
||||
} else if (newWidth < this.options.minWidth) {
|
||||
newWidth = this.options.minWidth;
|
||||
}
|
||||
});
|
||||
|
||||
this.$watch("content", function (val) {
|
||||
_this.editor.setDoc(prosemirror_dist_markdown.defaultMarkdownParser.parse(val));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = index;
|
||||
if (newWidth != el.getBoundingClientRect().width) {
|
||||
el.style.width = newWidth + "px";
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,61 @@
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory() :
|
||||
typeof define === 'function' && define.amd ? define(factory) :
|
||||
(factory());
|
||||
}(this, function () { 'use strict';
|
||||
|
||||
exports.install = function (Vue, options) {
|
||||
Vue.directive("input-autosize", {
|
||||
mirror: null,
|
||||
val: " ",
|
||||
options: {},
|
||||
bind: function bind() {
|
||||
var _this = this;
|
||||
|
||||
var defaults = { maxWidth: 500, minWidth: 20, comfortZone: 0 };
|
||||
this.options = Object.assign(defaults, options || {});
|
||||
|
||||
this.mirror = document.createElement("span");
|
||||
this.mirror.classList.add("vue-input-autosize-mirror");
|
||||
document.body.appendChild(this.mirror);
|
||||
|
||||
this.el.addEventListener("input", this.check.bind(this, this.el), false);
|
||||
setTimeout(function () {
|
||||
var styles = window.getComputedStyle(_this.el, null);
|
||||
Object.assign(_this.mirror.style, {
|
||||
position: "absolute",
|
||||
top: "-9999px",
|
||||
left: "-9999px",
|
||||
width: "auto",
|
||||
whiteSpace: "nowrap",
|
||||
fontSize: styles.getPropertyValue("font-size"),
|
||||
fontFamily: styles.getPropertyValue("font-family"),
|
||||
fontWeight: styles.getPropertyValue("font-weight"),
|
||||
letterSpacing: styles.getPropertyValue("letter-spacing"),
|
||||
textTransform: styles.getPropertyValue("text-transform"),
|
||||
ariaHidden: true
|
||||
});
|
||||
_this.check(_this.el);
|
||||
}, 0);
|
||||
},
|
||||
update: function update() {
|
||||
this.check(this.el);
|
||||
},
|
||||
check: function check(el) {
|
||||
this.val = el.value;
|
||||
if (!this.val) this.val = el.placeholder || "";
|
||||
this.mirror.innerHTML = this.val.replace(/&/g, "&").replace(/\s/g, " ").replace(/</g, "<").replace(/>/g, ">");
|
||||
var newWidth = this.mirror.getBoundingClientRect().width + this.options.comfortZone;
|
||||
if (newWidth > this.options.maxWidth) {
|
||||
newWidth = this.options.maxWidth;
|
||||
} else if (newWidth < this.options.minWidth) {
|
||||
newWidth = this.options.minWidth;
|
||||
}
|
||||
if (newWidth != el.getBoundingClientRect().width) {
|
||||
el.style.width = newWidth + "px";
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
}));
|
||||
+13
-13
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"name": "vue-prosemirror",
|
||||
"version": "0.1.2",
|
||||
"description": "A simple Vue.js wrapper around the ProseMirror editor",
|
||||
"name": "vue-input-autosize",
|
||||
"version": "0.1.0",
|
||||
"description": "A simple Vue.js directive to autosize text input fields",
|
||||
"license": "MIT",
|
||||
"repository": "syropian/vue-prosemirror",
|
||||
"repository": "syropian/vue-input-autosize",
|
||||
"author": {
|
||||
"name": "Collin Henderson",
|
||||
"email": "collin@syropia.net",
|
||||
@@ -13,9 +13,11 @@
|
||||
"node": ">=4"
|
||||
},
|
||||
"scripts": {
|
||||
"build:all": "npm run build && npm run build:umd",
|
||||
"build": "BUILD_ENV=cjs rollup -c",
|
||||
"build:umd": "BUILD_ENV=umd rollup -c",
|
||||
"example": "vbuild --dev -e example",
|
||||
"example:build": "vbuild -e example -t VueProsemirror"
|
||||
"example:build": "vbuild -e example -t VueInputAutosize"
|
||||
},
|
||||
"main": "index.js",
|
||||
"files": [
|
||||
@@ -23,18 +25,16 @@
|
||||
"index.umd.js"
|
||||
],
|
||||
"keywords": [
|
||||
"prosemirror",
|
||||
"editor",
|
||||
"markdown",
|
||||
"autosize",
|
||||
"autogrow",
|
||||
"autoshrink",
|
||||
"input",
|
||||
"Vue"
|
||||
],
|
||||
"dependencies": {
|
||||
"prosemirror": "^0.8.3"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"babel-preset-es2015-rollup": "^1.1.1",
|
||||
"rollup": "^0.33.0",
|
||||
"rollup-plugin-babel": "^2.6.1",
|
||||
"rollup-plugin-vue": "^2.0.1"
|
||||
"rollup-plugin-babel": "^2.6.1"
|
||||
}
|
||||
}
|
||||
|
||||
+6
-5
@@ -1,16 +1,17 @@
|
||||
import { rollup } from "rollup"
|
||||
import babel from "rollup-plugin-babel"
|
||||
import vue from "rollup-plugin-vue";
|
||||
|
||||
const env = process.env.BUILD_ENV
|
||||
const dest = env === "cjs" ? "index.js" : "index.umd.js"
|
||||
|
||||
export default {
|
||||
entry: "./src/index.vue",
|
||||
dest,
|
||||
entry: "./src/index.js",
|
||||
plugins: [
|
||||
vue()
|
||||
babel({
|
||||
exclude: "node_modules/**"
|
||||
})
|
||||
],
|
||||
dest,
|
||||
format: env,
|
||||
moduleName: "VueProseMirror"
|
||||
moduleName: "VueInputAutosize"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
"use strict";
|
||||
|
||||
exports.install = function(Vue, options){
|
||||
Vue.directive("input-autosize", {
|
||||
mirror: null,
|
||||
val: " ",
|
||||
options: {},
|
||||
bind(){
|
||||
const defaults = { maxWidth: 500, minWidth: 20, comfortZone: 0 };
|
||||
this.options = Object.assign(defaults, options || {});
|
||||
|
||||
this.mirror = document.createElement("span");
|
||||
this.mirror.classList.add("vue-input-autosize-mirror");
|
||||
document.body.appendChild(this.mirror);
|
||||
|
||||
this.el.addEventListener("input", this.check.bind(this, this.el), false);
|
||||
setTimeout(() => {
|
||||
let styles = window.getComputedStyle(this.el, null);
|
||||
Object.assign(this.mirror.style, {
|
||||
position: "absolute",
|
||||
top: "-9999px",
|
||||
left: "-9999px",
|
||||
width: "auto",
|
||||
whiteSpace: "nowrap",
|
||||
fontSize: styles.getPropertyValue("font-size"),
|
||||
fontFamily: styles.getPropertyValue("font-family"),
|
||||
fontWeight: styles.getPropertyValue("font-weight"),
|
||||
letterSpacing: styles.getPropertyValue("letter-spacing"),
|
||||
textTransform: styles.getPropertyValue("text-transform"),
|
||||
ariaHidden: true
|
||||
});
|
||||
this.check(this.el);
|
||||
}, 0)
|
||||
},
|
||||
update(){
|
||||
this.check(this.el);
|
||||
},
|
||||
check(el){
|
||||
this.val = el.value;
|
||||
if (!this.val) this.val = el.placeholder || "";
|
||||
this.mirror.innerHTML = this.val.replace(/&/g, "&").replace(/\s/g, " ").replace(/</g, "<").replace(/>/g, ">");
|
||||
let newWidth = this.mirror.getBoundingClientRect().width + this.options.comfortZone;
|
||||
if( newWidth > this.options.maxWidth ){ newWidth = this.options.maxWidth; }
|
||||
else if (newWidth < this.options.minWidth){ newWidth = this.options.minWidth; }
|
||||
if( newWidth != el.getBoundingClientRect().width ){ el.style.width = `${newWidth}px`; }
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
<template>
|
||||
<div class="vueProseMirror"></div>
|
||||
</template>
|
||||
<script>
|
||||
import prosemirror from "prosemirror";
|
||||
import { schema } from "prosemirror/dist/schema-basic";
|
||||
import { defaultMarkdownParser, defaultMarkdownSerializer } from "prosemirror/dist/markdown";
|
||||
import { exampleSetup, buildMenuItems } from "prosemirror/dist/example-setup";
|
||||
import { tooltipMenu, menuBar } from "prosemirror/dist/menu";
|
||||
export default {
|
||||
name: "ProseMirror",
|
||||
props: {
|
||||
content: String,
|
||||
onChange: Function,
|
||||
menuType: {
|
||||
type: String,
|
||||
default: "bar"
|
||||
},
|
||||
options: Object
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
editor: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
rawMarkdown(){
|
||||
return defaultMarkdownSerializer.serialize(this.editor.doc)
|
||||
},
|
||||
renderedContent(){
|
||||
let docFrag = this.editor.doc.content.toDOM();
|
||||
let div = document.createElement("div");
|
||||
div.appendChild( docFrag.cloneNode(true) );
|
||||
return div.innerHTML;
|
||||
}
|
||||
},
|
||||
ready(){
|
||||
const editorOptions = Object.assign({
|
||||
schema,
|
||||
place: this.el,
|
||||
doc: defaultMarkdownParser.parse(this.content),
|
||||
plugins: [exampleSetup.config({menuBar: false, tooltipMenu: false})]
|
||||
}, this.options);
|
||||
|
||||
if (editorOptions.doc === undefined || editorOptions.doc === null) {
|
||||
editorOptions.doc = null;
|
||||
editorOptions.docFormat = null;
|
||||
}
|
||||
|
||||
this.editor = new prosemirror.ProseMirror(editorOptions);
|
||||
|
||||
let menu = buildMenuItems(schema);
|
||||
if (this.menuType === "bar") {
|
||||
tooltipMenu.detach(this.editor);
|
||||
menuBar.config({float: true, content: menu.fullMenu}).attach(this.editor);
|
||||
}
|
||||
else {
|
||||
menuBar.detach(this.editor);
|
||||
tooltipMenu.config({
|
||||
selectedBlockMenu: true,
|
||||
inlineContent: menu.inlineMenu,
|
||||
blockContent: menu.blockMenu
|
||||
}).attach(this.editor);
|
||||
}
|
||||
|
||||
this.editor.on.change.add( () => {
|
||||
if( this.onChange && typeof this.onChange === "function" ){
|
||||
this.onChange.apply(null, [this.rawMarkdown, this.renderedContent])
|
||||
}
|
||||
});
|
||||
|
||||
this.$watch("content", (val) => {
|
||||
this.editor.setDoc(defaultMarkdownParser.parse(val));
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user