├── .babelrc
├── .eslintrc.js
├── .gitignore
├── .npmignore
├── README.md
├── demo
├── App.vue
├── cards
│ └── Test.vue
├── components
│ └── ToggleButton.vue
├── index.html
└── main.js
├── index.html
├── package-lock.json
├── package.json
├── src
├── MobiledocButton.js
├── MobiledocEditor.vue
├── addons
│ ├── MobiledocToolbar.js
│ └── compToCard.js
├── helpers
│ ├── mobiledocFormats.js
│ └── titlelize.js
└── index.js
├── test
├── e2e
│ ├── custom-assertions
│ │ └── elementCount.js
│ ├── nightwatch.conf.js
│ ├── runner.js
│ └── specs
│ │ └── test.js
└── unit
│ ├── .eslintrc
│ ├── coverage
│ ├── PhantomJS 2.1.1 (Mac OS X 0.0.0)
│ │ ├── base.css
│ │ ├── index.html
│ │ ├── prettify.css
│ │ ├── prettify.js
│ │ ├── sort-arrow-sprite.png
│ │ └── sorter.js
│ ├── lcov-report
│ │ ├── base.css
│ │ ├── components
│ │ │ ├── MobiledocEditor.vue.html
│ │ │ └── index.html
│ │ ├── index.html
│ │ ├── prettify.css
│ │ ├── prettify.js
│ │ ├── sort-arrow-sprite.png
│ │ ├── sorter.js
│ │ └── src
│ │ │ ├── App.vue.html
│ │ │ ├── Main.vue.html
│ │ │ ├── components
│ │ │ ├── MobiledocButton.vue.html
│ │ │ ├── MobiledocEditor.vue.html
│ │ │ ├── MobiledocLinkButton.vue.html
│ │ │ ├── MobiledocMarkupButton.vue.html
│ │ │ ├── MobiledocSectionButton.vue.html
│ │ │ └── index.html
│ │ │ ├── dev.js.html
│ │ │ ├── index.html
│ │ │ ├── index.js.html
│ │ │ └── utils
│ │ │ ├── index.html
│ │ │ └── titlelize.js.html
│ └── lcov.info
│ ├── index.js
│ ├── karma.conf.js
│ └── specs
│ ├── MobiledocButton.spec.js
│ ├── MobiledocController.spec.js
│ └── MobiledocEditor.spec.js
└── webpack.config.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["es2015", { "modules": false }],
4 | "stage-2"
5 | ],
6 | "plugins": ["transform-runtime", "transform-vue-jsx"],
7 | "comments": false
8 | }
9 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | parser: 'babel-eslint',
4 | env: {
5 | browser: true,
6 | node: true
7 | },
8 | extends: 'vue',
9 | // required to lint *.vue files
10 | plugins: [
11 | 'html'
12 | ],
13 | // add your custom rules here
14 | rules: {},
15 | globals: {}
16 | }
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .git
3 | node_modules/
4 | dist/
5 | npm-debug.log
6 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .babelrc
2 | webpack.config.js
3 | demo/
4 | test/
5 | src/
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Vue Mobiledoc Editor
2 |
3 | A Mobiledoc editor written using Vue and [Mobiledoc Kit](https://github.com/bustlelabs/mobiledoc-kit).
4 |
5 | ### Installation
6 |
7 | ```
8 | npm install vue-mobiledoc-editor
9 | ```
10 |
11 | The `vue-mobiledoc-editor` will install the `mobiledoc-kit` package as a dependency and load its assets.
12 |
13 | ### Basic Usage
14 |
15 | This package is composed of two main components:
16 |
17 | * `MobiledocEditor`
18 | * `MobiledocButton`
19 |
20 | Additionally, you can use the following addons:
21 | * `MobiledocToolbar` (component)
22 | * `compToCard` (factory function)
23 |
24 |
25 | The most basic usage with an empty editor and a standard toolbar is:
26 |
27 | ```
28 | // template
29 |
30 |
31 |
32 |
33 | // script
34 | import Mobiledoc, { MobiledocToolbar } from "vue-mobiledoc-editor"
35 |
36 | export default {
37 | components: {
38 | Editor: Mobiledoc.Editor,
39 | Toolbar: MobiledocToolbar
40 | }
41 | }
42 |
43 | ```
44 |
45 | You can check out the live `mobiledoc-kit` [demo](https://bustle.github.io/mobiledoc-kit/demo/) or clone the repo and run `npm run dev` for a more interactive example.
46 |
47 | Read on for how to provide custom configurations to each component.
48 |
49 | #### Mobiledoc Editor
50 |
51 | The mobiledoc editor is a component that accepts these Mobiledoc-specific props:
52 |
53 | * `mobiledoc`, a Mobiledoc to be edited. (*The package also exports an `EMPTY_MOBILEDOC` template that you can use as a default when passing a `mobiledoc` payload to the editor.*)
54 |
55 | * `atoms`, an array of available atoms for use by the editor.
56 |
57 | * `cards`, an array of available cards for use by the editor. (Jump to the section on Card-based components for details on how to create cards as Vue components.)
58 |
59 | * `cardOptions`, an object of additional props to pass to rendered cards.
60 |
61 | * `spellcheck`, a boolean. Defaults to true.
62 |
63 | * `autofocus`, a boolean. Defaults to true.
64 |
65 | * `placeholder`, a string to use as the placeholder text when the mobiledoc is blank.
66 |
67 | * `serializeVersion`, a string representing the mobiledoc version to serialize to when firing the `postWasUpdated` action. Defaults to 0.3.0.
68 |
69 | * 'enableEditing', a boolean that represents whether the editor is rendered in display or edit mode.
70 |
71 | Additionally, it can emit the following events:
72 |
73 | * `willCreateEditor`, a callback that fires when the Mobiledoc editor instance is about to be created. Takes no arguments.
74 |
75 | * `didCreateEditor`, a callback that fires once the Mobiledoc editor instance has been created. Will be called with the editor instance and may be used to configure it further.
76 |
77 | * `postWasUpdated`, a callback that will fire whenever the underlying document changes. It is called with the serialized mobiledoc.
78 |
79 | (*Note: For placeholder and other mobiledoc-related styles to work, you must import/copy mobiledoc-kit's [default CSS](https://github.com/bustle/mobiledoc-kit/blob/master/src/css/mobiledoc-kit.css) file yourself.*)
80 |
81 | Example usage:
82 |
83 | ```
84 |
87 |
88 | ```
89 |
90 | The editor has the following `refs` and `slots` available:
91 |
92 | ```HTML
93 |
94 |
95 |
96 |
97 |
98 |
99 | ```
100 |
101 | You can further manipulate the editor's post element (e.g. for styling) by using `$refs.editorPost`; or you can grab the editor instance directly using the `didCreateEditor` hook.
102 |
103 | Using `provide/inject`, the Editor also provides the `editorVm` to all child components. The `editorVM` has the following data and methods:
104 |
105 | * `editor`, a function that returns the Mobiledoc editor instance itself
106 |
107 | * `activeSectionTags`, an object with true values for section tag names in the current selection. For example activeSectionTagNames.isH1.
108 |
109 | * `activeMarkupTags`, an object with true values for markup tag names in the current selection. For example activeMarkupTagNames.isStrong
110 |
111 | * `canEdit`, a function that returns a boolean stating whether editing is currently enabled or disabled.
112 |
113 | * `toggleMarkup`, toggles the passed markup tag name in the current selection.
114 |
115 | * `toggleSection`, toggles the passed section tag name in the current selection.
116 |
117 | * `toggleLink`, toggles the linking of a selection. The user will be prompted for a URL if required.
118 |
119 | * `addAtom`, passed an atom `name`, `text`, and `payload`, will add that atom at the cursor position.
120 |
121 | * `addCard`, passed a card `name`, `payload`, and `editMode` will add that card at the end of a post and render it in the specified mode initially.
122 |
123 | * `toggleEditMode`, updates the `canEdit` state and toggles the edit mode of the mobiledoc editor.
124 |
125 | You can use the `MobiledocEditor.editor` instance itself to take full advantage of the features in the [mobiledoc-kit API documentation](http://bustlelabs.github.io/mobiledoc-kit/demo/docs/).
126 |
127 |
128 | #### Mobiledoc Button
129 |
130 | The `MobiledocButton` is a functional component that delegates the passed `props` to the appropriate button. Because of this, *every button requires* the `type` prop. Any additional props depend on the type of button.
131 |
132 | There are five types of buttons:
133 |
134 | * `MarkupButton`, requires a `tag` prop to identify the type of markup to toggle.
135 |
136 | * `SectionButton`, requires a `tag` prop to identify the type of section to toggle.
137 |
138 | * `LinkButton`, accepts an optional `prompt` prop that you can pass if you wish to provide a custom dialog that the user will shown when prompted input the link.
139 |
140 | * `AtomButton`, requires a `name` prop to identify the atom that will be added to the end of the post and accepts an optional `text` and `payload` prop.
141 |
142 | * `CardButton`, requires a `name` prop to identify the card that will be added to the end of the post and accepts an optional `payload` and `mode` prop. There are two `mode` options, `edit` or `display`; the default is `display`.
143 |
144 | Additionally, all buttons accept a`label` prop, to set the content of the button when used as a blockless component.
145 |
146 | Example usage:
147 |
148 | ```
149 |
150 | ```
151 |
152 | #### Mobiledoc Toolbar
153 |
154 | The component creates a standard toolbar for the mobiledoc editor.
155 |
156 | Example usage:
157 |
158 | ```
159 |
160 | ```
161 |
162 | ### Advanced Usage
163 |
164 | #### Component Cards
165 |
166 | Mobiledoc supports "cards", blocks of rich content that are embedded into a post.
167 |
168 | `vue-mobiledoc-editor` comes with a helper for using your own Vue components as the display and edit modes of a card.
169 |
170 | The card's properties are passed as props to the component. You can use them like this:
171 |
172 | ```
173 | // components/cards/example.vue
174 |
175 |
176 |
177 |
{{ msg }}
178 |
179 |
180 |
181 |
192 |
193 | ```
194 | Then, to use the component as a card, wrap your own component in the `compToCard`
195 | serializer function, before passing it to the editor as a card option:
196 |
197 | ```
198 | // components/editor.js
199 |
200 |
201 |
202 | exCard
203 |
204 |
205 |
206 |
207 |
223 | ```
224 |
225 | Please note that your card must have a name to identify it. So if your component does not have a name, you'll need to provide your own to the serializer function: `compToCard(NamelessComponent, 'MyCardName')`.
226 |
227 | The following mobiledoc-specific properties are passed to the component:
228 |
229 | - `env`, an object of that holds environment-specific properties
230 | - `payload`, an object that holds the data payload retrieved from the mobiledoc for this card
231 |
232 | For more details on the API for authoring cards in vanilla JavaScript, as welll as the `env` properties available to the card, see [CARDS.md](https://github.com/bustlelabs/mobiledoc-kit/blob/master/CARDS.md).
233 |
234 | #### Creating custom mobiledoc components
235 |
236 | To create components that control the mobiledoc editor, just inject the `editorVm` to child components.
237 |
238 | For example, you can create a button that toggles whether the editor is editable or not:
239 |
240 | ```
241 | export default {
242 | inject: ['editorVm']
243 | render(h) {
244 | const { canEdit, toggleEditMode } = this.editorVm
245 | return h(
246 |
249 | )
250 | }
251 | }
252 | ```
253 |
254 | *Note: Mobiledoc components must be nested under the Mobiledoc `Editor`.*
255 |
256 | ## Development
257 |
258 | To get started:
259 |
260 | * `git clone` this repository
261 |
262 | * `npm install`
263 |
264 |
265 | Run the development server:
266 |
267 | A development server is available under the `/demo` directory. You can check out the demo for an example of basic usage or to interactively test your contribution.
268 |
269 | * `npm run dev` from project root
270 |
271 | * Visit your app at `http://localhost:8080`.
272 |
273 |
274 | Run tests:
275 |
276 | * `npm run unit`
277 |
278 |
279 | Build to `dist/`:
280 |
281 | * `npm run build`
282 |
283 |
284 | #### Getting Help
285 |
286 | If you'd like to report a bug or request a feature, please [open an issue](https://github.com/studbits/vue-mobiledoc-editor/issues).
287 |
--------------------------------------------------------------------------------
/demo/App.vue:
--------------------------------------------------------------------------------
1 |
2 |