├── .gitignore ├── LICENSE ├── README.ja.md ├── README.md ├── TODO ├── babel.config.js ├── dist ├── css │ └── style.css ├── favicon.ico ├── index.html └── js │ ├── block-editor-vue.js │ ├── development.js │ └── production.js ├── package-lock.json ├── package.json ├── public ├── css │ └── style.css ├── favicon.ico ├── index.html └── js │ ├── development.js │ └── production.js ├── screenshot.png ├── src ├── App.vue ├── components │ ├── Column.vue │ ├── Heading.vue │ ├── Html.vue │ ├── List.vue │ ├── Paragraph.vue │ ├── Table.vue │ ├── icons │ │ ├── IconAlignCenter.vue │ │ ├── IconAlignLeft.vue │ │ ├── IconAlignRight.vue │ │ ├── IconArrowDown.vue │ │ ├── IconArrowUp.vue │ │ ├── IconBold.vue │ │ ├── IconCheck.vue │ │ ├── IconClipboard.vue │ │ ├── IconClose.vue │ │ ├── IconColumn.vue │ │ ├── IconCssClass.vue │ │ ├── IconDelete.vue │ │ ├── IconEllipsisH.vue │ │ ├── IconEllipsisV.vue │ │ ├── IconEraser.vue │ │ ├── IconGrid.vue │ │ ├── IconHeading.vue │ │ ├── IconHtml.vue │ │ ├── IconImage.vue │ │ ├── IconInputClear.vue │ │ ├── IconLink.vue │ │ ├── IconList.vue │ │ ├── IconMovedown.vue │ │ ├── IconMoveup.vue │ │ ├── IconParagraph.vue │ │ ├── IconPlus.vue │ │ ├── IconPlusBig.vue │ │ ├── IconRedo.vue │ │ ├── IconReplicate.vue │ │ ├── IconTable.vue │ │ ├── IconTableMenu.vue │ │ ├── IconUndo.vue │ │ └── IconUnlink.vue │ └── sub │ │ ├── ActionMenu.vue │ │ ├── AddMenu.vue │ │ ├── BrokenImage.vue │ │ ├── Checkbox.vue │ │ ├── ClassInput.vue │ │ ├── ColumnEdit.vue │ │ ├── ComponentBase.vue │ │ ├── HeadingLevelEdit.vue │ │ ├── IconBase.vue │ │ ├── ImageEdit.vue │ │ ├── ImageList.vue │ │ ├── ItemHeader.vue │ │ ├── ItemMixin.vue │ │ ├── ListTypeEdit.vue │ │ ├── PlainText.vue │ │ ├── RangeInput.vue │ │ ├── Separator.vue │ │ ├── SwitchInput.vue │ │ ├── TableCell.vue │ │ ├── TableCellMenu.vue │ │ ├── TableColMenu.vue │ │ ├── TableColResizeMixin.vue │ │ ├── TableManagerMixin.vue │ │ ├── TableRowMenu.vue │ │ ├── TableSizeEdit.vue │ │ ├── TableSortMixin.vue │ │ ├── TextInput.vue │ │ └── VisualText.vue ├── i18n │ ├── en.json │ ├── ja.json │ └── load.js ├── main.js ├── scripts │ ├── DOM.js │ ├── DragItemUtil.js │ ├── ItemBase.js │ ├── LoadComponents.js │ └── Util.js └── styles │ ├── animation.scss │ ├── components.scss │ ├── reset.scss │ ├── v-tooltip.scss │ └── valiables.scss └── vue.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | 4 | # local env files 5 | .env.local 6 | .env.*.local 7 | 8 | # Log files 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | 13 | # Editor directories and files 14 | .idea 15 | .vscode 16 | *.suo 17 | *.ntvs* 18 | *.njsproj 19 | *.sln 20 | *.sw* 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright 2019 takitakit 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | * 足らないアイコン 2 | * CKFinder、Froalaなどのアップローダとの連携 3 | * テーブル列の移動の際のボーダーがずれる 4 | * preset setをitemsで設定したときに、preset setとして画面に表示されない 5 | * 非minifyファイルの生成 -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/app' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /dist/css/style.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | padding: 0; 3 | margin: 0; 4 | font-size: 16px; 5 | position: relative; 6 | } 7 | .content { 8 | width: 100%; 9 | position: relative; 10 | } 11 | div[id^="jsFrame"] { 12 | z-index: 10000; 13 | } 14 | #preview { 15 | width: 100%; 16 | height: 100%; 17 | box-sizing: border-box; 18 | overflow: auto; 19 | padding: 10px; 20 | font-size: 1rem; 21 | color:#555; 22 | 23 | } 24 | @media screen and (max-width:465px) { 25 | /* hide preview on small display */ 26 | div[id^="jsFrame"] { 27 | display: none; 28 | } 29 | } 30 | 31 | /* プレビュー用スタイル */ 32 | .preview-body .ve > * { 33 | box-sizing: border-box; 34 | width: 100%; 35 | box-sizing: border-box; 36 | } 37 | 38 | /* Heading */ 39 | .preview-body h1 { 40 | font-size: 2.0rem; 41 | font-weight: bold; 42 | margin: .5rem 0px; 43 | } 44 | .preview-body h2 { 45 | font-size: 1.8rem; 46 | font-weight: bold; 47 | margin: .5rem 0px; 48 | } 49 | .preview-body h3 { 50 | font-size: 1.5rem; 51 | font-weight: bold; 52 | margin: .5rem 0px; 53 | } 54 | .preview-body h4 { 55 | font-size: 1.4rem; 56 | font-weight: bold; 57 | margin: .5rem 0px; 58 | } 59 | .preview-body h5 { 60 | font-size: 1.2rem; 61 | font-weight: bold; 62 | margin: .5rem 0px; 63 | } 64 | .preview-body h6 { 65 | font-size: 1.1rem; 66 | font-weight: bold; 67 | margin: .5rem 0px; 68 | } 69 | 70 | /* Paragraph */ 71 | .preview-body .paragraph-wrap { 72 | margin: 1rem 0; 73 | } 74 | .preview-body .paragraph-wrap::after { 75 | content: ""; 76 | display: block; 77 | clear: both; 78 | } 79 | .preview-body .paragraph-wrap .images { 80 | box-sizing: border-box; 81 | position: relative; 82 | } 83 | .preview-body .paragraph-wrap .images .image { 84 | position: relative; 85 | font-size: 0; 86 | margin: .5rem 0 0 0; 87 | } 88 | .preview-body .paragraph-wrap .images .image .caption { 89 | position: absolute; 90 | bottom: 0; 91 | left: 0; 92 | font-size: .8rem; 93 | width: 100%; 94 | background-color: rgba(0,0,0,.3); 95 | color: #fff; 96 | box-sizing: border-box; 97 | padding: 3px 5px; 98 | } 99 | .preview-body .paragraph-wrap .images .image { 100 | width: 100%; 101 | } 102 | .preview-body .paragraph-wrap .images .image img { 103 | width: 100%; 104 | } 105 | .preview-body .paragraph-wrap .images .image::last-child { 106 | margin: 0; 107 | } 108 | 109 | .preview-body .paragraph-wrap.align-left .images { 110 | margin: 0 .5rem 0 0; 111 | float: left; 112 | width: 40%; 113 | } 114 | 115 | .preview-body .paragraph-wrap.align-right .images { 116 | margin: 0 0 0 .5rem; 117 | float: right; 118 | width: 40%; 119 | } 120 | .preview-body .paragraph-wrap.align-center .images { 121 | margin: 0 auto; 122 | width: 50%; 123 | max-width: 80%; 124 | } 125 | 126 | /* List */ 127 | .preview-body ol { 128 | padding: 0 0 0 1rem; 129 | } 130 | .preview-body ul { 131 | padding: 0 0 0 1rem; 132 | list-style-type: disc; 133 | } 134 | 135 | /* Table */ 136 | .preview-body table { 137 | border-collapse: collapse; 138 | border: 1px solid #aaa; 139 | table-layout: fixed; 140 | } 141 | .preview-body table th, 142 | .preview-body table td { 143 | border: 1px solid #aaa; 144 | padding: 3px; 145 | } 146 | .preview-body table th { 147 | background-color: #ddd; 148 | color: #444; 149 | } 150 | 151 | /* Column */ 152 | .preview-body .column-wrap { 153 | margin: 1rem 0; 154 | display: flex; 155 | flex-wrap: nowrap; 156 | border: 1px solid #ccc; 157 | } 158 | .preview-body .column-wrap .column-item { 159 | padding: .5rem; 160 | flex: 1; 161 | } 162 | .preview-body .column-wrap .paragraph-wrap.align-left .images, 163 | .preview-body .column-wrap .paragraph-wrap.align-right .images { 164 | width: 60%; 165 | } 166 | 167 | /* Visual Editor */ 168 | .preview-body .ve-bold, 169 | .BEV-block-editor .ve-bold { 170 | font-weight: bold; 171 | } 172 | .preview-body .ve-highlight, 173 | .BEV-block-editor .ve-highlight { 174 | background-color: yellow; 175 | } 176 | .preview-body .ve-underline, 177 | .BEV-block-editor .ve-underline { 178 | text-decoration: underline; 179 | } 180 | .preview-body .ve-red, 181 | .BEV-block-editor .ve-red { 182 | color: red; 183 | } 184 | .preview-body .ve-blue, 185 | .BEV-block-editor .ve-blue { 186 | color: blue; 187 | } 188 | .preview-body .ve-green, 189 | .BEV-block-editor .ve-green { 190 | color: green; 191 | } -------------------------------------------------------------------------------- /dist/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/takitakit/block-editor-vue/73b10634ec9dab2bab2cc9714515f8e84a014034/dist/favicon.ico -------------------------------------------------------------------------------- /dist/index.html: -------------------------------------------------------------------------------- 1 | block-editor-vue
-------------------------------------------------------------------------------- /dist/js/development.js: -------------------------------------------------------------------------------- 1 | let options 2 | const merge_cell = { content: 'merged cell', header: true, rowspan: 3, colspan: 3 }; 3 | const merge_cell2 = { content: 'merged cell2', header: true, rowspan: 1, colspan: 2 }; 4 | const items = [ 5 | { 6 | name: 'Heading', 7 | className: 'title', 8 | level: 'h2', 9 | content: 'hoge' 10 | }, 11 | { 12 | name: 'Table', 13 | rows: [ 14 | { 15 | cells: [ 16 | { content: 'C1-1', header: true }, 17 | { content: 'C1-2', header: true }, 18 | { content: 'C1-3', header: true }, 19 | merge_cell2, 20 | { dummy: true, content: '', ref: merge_cell2 } 21 | ] 22 | }, 23 | { 24 | cells: [ 25 | { content: 'C2-1', header: false }, 26 | merge_cell, 27 | { content: '', dummy: true, ref: merge_cell }, 28 | { content: '', dummy: true, ref: merge_cell }, 29 | { content: 'C2-5' } 30 | ] 31 | }, 32 | { 33 | cells: [ 34 | { content: 'C3-1', header: false }, 35 | { content: '', dummy: true, ref: merge_cell }, 36 | { content: '', dummy: true, ref: merge_cell }, 37 | { content: '', dummy: true, ref: merge_cell }, 38 | { content: 'C3-5' } 39 | ] 40 | }, 41 | { 42 | cells: [ 43 | { content: 'C4-1', header: false }, 44 | { content: '', dummy: true, ref: merge_cell }, 45 | { content: '', dummy: true, ref: merge_cell }, 46 | { content: '', dummy: true, ref: merge_cell }, 47 | { content: 'C4-5' } 48 | ] 49 | }, 50 | { 51 | cells: [ 52 | { content: 'C5-1', header: false }, 53 | { content: 'C5-2', header: false }, 54 | { content: 'C5-3', header: false }, 55 | { content: 'C5-4', header: false }, 56 | { content: 'C5-5', header: false } 57 | ] 58 | } 59 | ], 60 | colgroup: [ 61 | { width: null }, 62 | { width: null }, 63 | { width: null }, 64 | { width: null }, 65 | { width: null }, 66 | ] 67 | }, 68 | { 69 | name: 'List', 70 | // type: 'unordered', 71 | className: 'test', 72 | rows: [ 73 | { content: 'リスト1
太字テスト' }, 74 | { content: 'リスト2' }, 75 | { content: 'リスト3' }, 76 | { content: 'リスト4' } 77 | ] 78 | }, 79 | { 80 | name: 'Paragraph', 81 | imageAlign: 'left', 82 | className: 'testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttest', 83 | images: [ 84 | { src: 'https://placehold.jp/3d4070/ffffff/150x150.png', caption: 'caption1' }, 85 | { src: 'https://placehold.jp/c122cc/ffffff/300x200.png', caption: 'caption2' }, 86 | { src: 'https://placehold.jp/22cca4/ffffff/200x300.png', caption: 'caption3' } 87 | ], 88 | content: 'externalリンク文章が入ります。internalリンク太字文章が入ります。
文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。' 89 | }, 90 | { 91 | name: 'Paragraph', 92 | imageAlign: 'left', 93 | className: 'testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttest', 94 | images: [ 95 | { src: 'https://placeholds.jp/3d4070/ffffff/150x150.png', caption: 'caption1' }, 96 | { src: 'https://placehold.jp/c122cc/ffffff/300x200.png', caption: 'caption2' }, 97 | { src: 'https://placehold.jp/22cca4/ffffff/200x300.png', caption: 'caption3' } 98 | ], 99 | content: '文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。' 100 | }, 101 | { 102 | name: 'Html', 103 | content: '
hoge
' 104 | }, 105 | { 106 | name: 'Column', 107 | className: 'aaaa', 108 | columns: [ 109 | { 110 | items: [ 111 | { 112 | name: 'Paragraph', 113 | imageAlign: 'left', 114 | className: 'testtesttesttesttesttesttesttest', 115 | images: [], 116 | content: '' 117 | }, 118 | { 119 | name: 'Paragraph', 120 | imageAlign: 'right', 121 | className: null, 122 | images: [], 123 | content: '' 124 | } 125 | ] 126 | }, 127 | { 128 | items: [ 129 | { name: 'Html' } 130 | ] 131 | }, 132 | { 133 | items: [ 134 | { 135 | name: 'Paragraph', 136 | imageAlign: 'left', 137 | className: null, 138 | images: [], 139 | content: '' 140 | } 141 | ] 142 | } 143 | ] 144 | }, 145 | { 146 | name: 'Column', 147 | columns: [ 148 | { items: [] }, { items: [] } 149 | ] 150 | }, 151 | { 152 | name: 'Paragraph', 153 | imageAlign: 'left', 154 | className: 'testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttest', 155 | images: [], 156 | content: '' 157 | } 158 | ]; 159 | 160 | options = { 161 | locale: 'ja', 162 | items: items, 163 | // enabledItemNames: ['Html', 'Table'], 164 | // enabledItemNamesInColumn: ['Html'], 165 | loadItemsFromInputTag: true, 166 | allowHistories: true, 167 | allowStyledText: true, 168 | allowCssClass: true, 169 | allowFileBrowser: true, 170 | // itemOrder: [ // メニュー上のアイテムの表示順序 171 | // 'Heading', 'Image', 'List', 'Table', 'Column', 'Html', 'Paragraph' 172 | // ], 173 | FileBrowser: { 174 | url: 'http://localhost:8888/elfinder/', 175 | width: '80%', 176 | height: '80%', 177 | resizable: true, 178 | }, 179 | // cssClasses: [ 180 | // 'class1', 'class2', 181 | // {class3: 'クラス3'}, {'test-class': 'テストクラス'} 182 | // ], 183 | styledTextClasses: [ 184 | 'bold', 'link', 185 | { red: '赤字' }, { blue: '青字' }, { green: '緑字' }, 186 | { underline: '下線' }, { highlight: 'ハイライト' } 187 | ], 188 | Paragraph: { 189 | allowImages: true, 190 | defaultImageAlign: 'right', 191 | dispName: 'テキスト', 192 | presets: [ 193 | { className: 'important', dispName: '重要' }, 194 | { className: 'normal', dispName: '通常' }, 195 | { imageAlign: 'center', dispName: '中央揃え画像' } 196 | ], 197 | }, 198 | List: { 199 | maxRows: 10, 200 | allowStyledText: true, 201 | presets: [ 202 | { className: 'link', type: 'unordered', dispName: 'リンクリスト' }, 203 | { type: 'unordered', dispName: '通常リスト' }, 204 | { type: 'ordered', dispName: '箇条書きリスト' } 205 | ] 206 | }, 207 | Table: { 208 | maxRow: 10, // テーブルの最大行数 209 | maxCol: 10, // テーブルの最大列数 210 | minRow: 1, // テーブルの最小行数 211 | minCol: 2, // テーブルの最小列数 212 | presets: [ 213 | { className: 'product', dispName: '商品テーブル' }, 214 | { dispName: '通常テーブル' } 215 | ] 216 | }, 217 | Heading: { 218 | levels: ['h2', 'h3', 'h4', 'h5', 'h6'], 219 | // levels: ['h3'], 220 | levelNames: { h2: '超大見出し', h3: '大見出し', h4: '中見出し', h5: '小見出し', h6: '超小見出し' }, 221 | defaultLevel: 'h3', 222 | presets: [ 223 | { className: 'title', level: 'h2', dispName: 'タイトル' }, 224 | { className: 'sub-title', level: 'h3', dispName: 'サブタイトル' } 225 | ] 226 | }, 227 | Column: { 228 | allowChangeNumColumn: true, // カラム数の変更許可 229 | defaultNumColumn: 2, // デフォルトのカラム数 230 | maxColumn: 5, // 段組の最大数 231 | minColumn: 2, // 段組の最小数 232 | presets: [ 233 | { className: 'special', dispName: '特集カラム' }, 234 | { className: 'normal', dispName: '通常カラム' } 235 | ] 236 | }, 237 | onLoad: function (html) { 238 | updatePreview(html); 239 | }, 240 | onUpdate: function (html) { 241 | updatePreview(html); 242 | } 243 | }; 244 | const instance = new BlockEditor('#app1', options); 245 | 246 | // Update preview 247 | var previewBody; 248 | function updatePreview(html) { 249 | if (previewBody) { 250 | previewBody.innerHTML = html; 251 | } else { 252 | launchPreview(html); 253 | previewBody = document.querySelector('#preview'); 254 | } 255 | } 256 | 257 | // Preview window 258 | function launchPreview (html) { 259 | var jsFrame = new JSFrame({ 260 | horizontalAlign: 'left', 261 | verticalAlign: 'top', 262 | }); 263 | var frame = jsFrame.create({ 264 | title: 'Preview', 265 | left: 200, top: 200, width: 600, height: 400, minWidth: 300, minHeight: 200, 266 | appearanceName: 'material', 267 | appearanceParam: { 268 | border: { 269 | shadow: '0px 0px 6px -3px rgba(0,0,0,0.42)', 270 | width: 1, 271 | color: 'rgba(0,0,0,.15)', 272 | radius: 4, 273 | }, 274 | titleBar: { 275 | background: 'rgba(97, 104, 111, 1.0)' 276 | } 277 | }, 278 | style: { 279 | backgroundColor: 'rgba(255,255,255,0.88)', 280 | overflow: 'auto' 281 | }, 282 | html: '
' + html + '
' 283 | }); 284 | frame.show(); 285 | 286 | frame.setControl({ 287 | maximizeButton: 'maximizeButton', 288 | demaximizeButton: 'restoreButton', 289 | minimizeButton: 'minimizeButton', 290 | deminimizeButton: 'deminimizeButton', 291 | animation: true, 292 | animationDuration: 200, 293 | }); 294 | } 295 | -------------------------------------------------------------------------------- /dist/js/production.js: -------------------------------------------------------------------------------- 1 | var options 2 | var tbl_head_row = { 3 | header: true, 4 | content: 'Table content', 5 | colspan: 3 6 | } 7 | options = { 8 | items: [ 9 | { 10 | name: 'Heading', 11 | level: 'h1', 12 | content: 'Extra-big heading' 13 | }, 14 | { 15 | name: 'Heading', 16 | level: 'h2', 17 | content: 'Big heading' 18 | }, 19 | { 20 | name: 'Heading', 21 | level: 'h3', 22 | content: 'Medium heading' 23 | }, 24 | { 25 | name: 'Heading', 26 | level: 'h4', 27 | content: 'Small heading' 28 | }, 29 | { 30 | name: 'Heading', 31 | level: 'h5', 32 | content: 'Extra-small heading' 33 | }, 34 | { 35 | name: 'Heading', 36 | level: 'h6', 37 | content: 'Minimum heading' 38 | }, 39 | { 40 | name: 'Paragraph', 41 | content: 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a', 42 | }, 43 | { 44 | name: 'Paragraph', 45 | imageAlign: 'left', 46 | images: [ 47 | { src: 'https://placehold.jp/3d4070/ffffff/600x400.png?text=Dummy', 'caption': 'Dummy caption' } 48 | ], 49 | content: 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a', 50 | }, 51 | { 52 | name: 'List', 53 | type: 'unordered', 54 | rows: [ 55 | { content: 'This is the text of the list' }, 56 | { content: 'This is the text of the list' }, 57 | { content: 'This is the text of the list' } 58 | ] 59 | }, 60 | { 61 | name: 'List', 62 | type: 'ordered', 63 | rows: [ 64 | { content: 'This is the text of the list' }, 65 | { content: 'This is the text of the list' }, 66 | { content: 'This is the text of the list' } 67 | ] 68 | }, 69 | { 70 | name: 'Table', 71 | rows: [ 72 | { 73 | cells: [ 74 | tbl_head_row, 75 | { dummy: true, ref: tbl_head_row }, 76 | { dummy: true, ref: tbl_head_row } 77 | ] 78 | }, 79 | { 80 | cells: [ 81 | { 82 | header: true, 83 | content: 'header cell' 84 | }, 85 | { 86 | content: 'cell' 87 | }, 88 | { 89 | content: 'cell' 90 | } 91 | ] 92 | }, 93 | { 94 | cells: [ 95 | { 96 | header: true, 97 | content: 'header cell' 98 | }, 99 | { 100 | content: 'cell' 101 | }, 102 | { 103 | content: 'cell' 104 | } 105 | ] 106 | } 107 | ] 108 | }, 109 | { 110 | name: 'Column', 111 | columns: [ 112 | { 113 | items: [ 114 | { 115 | name: 'Heading', 116 | level: 'h3', 117 | content: 'Heading in a column' 118 | }, 119 | { 120 | name: 'Paragraph', 121 | images: [ 122 | { src: 'https://placehold.jp/3d4070/ffffff/400x300.png?text=Dummy', caption: 'Image caption' } 123 | ], 124 | content: 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo' 125 | } 126 | ] 127 | }, 128 | { 129 | items: [ 130 | { 131 | name: 'List', 132 | type: 'unoradered', 133 | rows: [ 134 | { content: 'This is the text of the list in a column' }, 135 | { content: 'This is the text of the list in a column' }, 136 | { content: 'This is the text of the list in a column' } 137 | ] 138 | } 139 | ] 140 | } 141 | ] 142 | }, 143 | { 144 | name: 'Html', 145 | content: '
Here is a raw html
' 146 | } 147 | ], 148 | loadItemsFromInputTag: false, 149 | allowStyledText: true, 150 | styledTextClasses: ['bold','link','red','green','blue'], 151 | onLoad: function (html) { 152 | updatePreview(html); 153 | }, 154 | onUpdate: function (html) { 155 | updatePreview(html); 156 | } 157 | }; 158 | new BlockEditor('#app1', options); 159 | 160 | // Update preview 161 | var previewBody; 162 | function updatePreview(html) { 163 | if (previewBody) { 164 | previewBody.innerHTML = html; 165 | } else { 166 | launchPreview(html); 167 | previewBody = document.querySelector('#preview'); 168 | } 169 | } 170 | 171 | // Preview window 172 | function launchPreview(html) { 173 | var jsFrame = new JSFrame({ 174 | horizontalAlign: 'left', 175 | verticalAlign: 'top', 176 | }); 177 | var frame = jsFrame.create({ 178 | title: 'Preview', 179 | left: 200, top: 200, width: 600, height: 400, minWidth: 300, minHeight: 200, 180 | appearanceName: 'material', 181 | appearanceParam: { 182 | border: { 183 | shadow: '0px 0px 6px -3px rgba(0,0,0,0.42)', 184 | width: 1, 185 | color: 'rgba(0,0,0,.15)', 186 | radius: 4, 187 | }, 188 | titleBar: { 189 | background: 'rgba(97, 104, 111, 1.0)' 190 | } 191 | }, 192 | style: { 193 | backgroundColor: 'rgba(255,255,255,0.88)', 194 | overflow: 'auto' 195 | }, 196 | html: '
' + html + '
' 197 | }); 198 | frame.show(); 199 | 200 | frame.setControl({ 201 | maximizeButton: 'maximizeButton', 202 | demaximizeButton: 'restoreButton', 203 | minimizeButton: 'minimizeButton', 204 | deminimizeButton: 'deminimizeButton', 205 | animation: true, 206 | animationDuration: 200, 207 | }); 208 | } 209 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "block-editor-vue", 3 | "version": "1.0.3", 4 | "private": false, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "lodash": "^4.17.11", 12 | "quill": "^1.3.6", 13 | "terser": "^3.17.0", 14 | "v-tooltip": "^2.0.2", 15 | "vue": "^2.6.10", 16 | "vue-i18n": "^8.11.2", 17 | "vuex": "^3.1.0" 18 | }, 19 | "devDependencies": { 20 | "@vue/cli-plugin-babel": "^3.7.0", 21 | "@vue/cli-plugin-eslint": "^3.7.0", 22 | "@vue/cli-service": "^3.7.0", 23 | "babel-eslint": "^10.0.1", 24 | "eslint": "^5.16.0", 25 | "eslint-plugin-vue": "^5.2.2", 26 | "node-sass": "^4.12.0", 27 | "sass-loader": "^7.1.0", 28 | "vue-template-compiler": "^2.6.10" 29 | }, 30 | "eslintConfig": { 31 | "root": true, 32 | "env": { 33 | "node": true 34 | }, 35 | "extends": [ 36 | "plugin:vue/essential", 37 | "eslint:recommended" 38 | ], 39 | "rules": { 40 | "no-unused-vars": 0, 41 | "no-constant-condition": 0 42 | }, 43 | "parserOptions": { 44 | "parser": "babel-eslint" 45 | } 46 | }, 47 | "postcss": { 48 | "plugins": { 49 | "autoprefixer": {} 50 | } 51 | }, 52 | "browserslist": [ 53 | "> 1%", 54 | "last 2 versions", 55 | "not ie <= 8" 56 | ] 57 | } 58 | -------------------------------------------------------------------------------- /public/css/style.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | padding: 0; 3 | margin: 0; 4 | font-size: 16px; 5 | position: relative; 6 | } 7 | .content { 8 | width: 100%; 9 | position: relative; 10 | } 11 | div[id^="jsFrame"] { 12 | z-index: 10000; 13 | } 14 | #preview { 15 | width: 100%; 16 | height: 100%; 17 | box-sizing: border-box; 18 | overflow: auto; 19 | padding: 10px; 20 | font-size: 1rem; 21 | color:#555; 22 | 23 | } 24 | @media screen and (max-width:465px) { 25 | /* hide preview on small display */ 26 | div[id^="jsFrame"] { 27 | display: none; 28 | } 29 | } 30 | 31 | /* プレビュー用スタイル */ 32 | .preview-body .ve > * { 33 | box-sizing: border-box; 34 | width: 100%; 35 | box-sizing: border-box; 36 | } 37 | 38 | /* Heading */ 39 | .preview-body h1 { 40 | font-size: 2.0rem; 41 | font-weight: bold; 42 | margin: .5rem 0px; 43 | } 44 | .preview-body h2 { 45 | font-size: 1.8rem; 46 | font-weight: bold; 47 | margin: .5rem 0px; 48 | } 49 | .preview-body h3 { 50 | font-size: 1.5rem; 51 | font-weight: bold; 52 | margin: .5rem 0px; 53 | } 54 | .preview-body h4 { 55 | font-size: 1.4rem; 56 | font-weight: bold; 57 | margin: .5rem 0px; 58 | } 59 | .preview-body h5 { 60 | font-size: 1.2rem; 61 | font-weight: bold; 62 | margin: .5rem 0px; 63 | } 64 | .preview-body h6 { 65 | font-size: 1.1rem; 66 | font-weight: bold; 67 | margin: .5rem 0px; 68 | } 69 | 70 | /* Paragraph */ 71 | .preview-body .paragraph-wrap { 72 | margin: 1rem 0; 73 | } 74 | .preview-body .paragraph-wrap::after { 75 | content: ""; 76 | display: block; 77 | clear: both; 78 | } 79 | .preview-body .paragraph-wrap .images { 80 | box-sizing: border-box; 81 | position: relative; 82 | } 83 | .preview-body .paragraph-wrap .images .image { 84 | position: relative; 85 | font-size: 0; 86 | margin: .5rem 0 0 0; 87 | } 88 | .preview-body .paragraph-wrap .images .image .caption { 89 | position: absolute; 90 | bottom: 0; 91 | left: 0; 92 | font-size: .8rem; 93 | width: 100%; 94 | background-color: rgba(0,0,0,.3); 95 | color: #fff; 96 | box-sizing: border-box; 97 | padding: 3px 5px; 98 | } 99 | .preview-body .paragraph-wrap .images .image { 100 | width: 100%; 101 | } 102 | .preview-body .paragraph-wrap .images .image img { 103 | width: 100%; 104 | } 105 | .preview-body .paragraph-wrap .images .image::last-child { 106 | margin: 0; 107 | } 108 | 109 | .preview-body .paragraph-wrap.align-left .images { 110 | margin: 0 .5rem 0 0; 111 | float: left; 112 | width: 40%; 113 | } 114 | 115 | .preview-body .paragraph-wrap.align-right .images { 116 | margin: 0 0 0 .5rem; 117 | float: right; 118 | width: 40%; 119 | } 120 | .preview-body .paragraph-wrap.align-center .images { 121 | margin: 0 auto; 122 | width: 50%; 123 | max-width: 80%; 124 | } 125 | 126 | /* List */ 127 | .preview-body ol { 128 | padding: 0 0 0 1rem; 129 | } 130 | .preview-body ul { 131 | padding: 0 0 0 1rem; 132 | list-style-type: disc; 133 | } 134 | 135 | /* Table */ 136 | .preview-body table { 137 | border-collapse: collapse; 138 | border: 1px solid #aaa; 139 | table-layout: fixed; 140 | } 141 | .preview-body table th, 142 | .preview-body table td { 143 | border: 1px solid #aaa; 144 | padding: 3px; 145 | } 146 | .preview-body table th { 147 | background-color: #ddd; 148 | color: #444; 149 | } 150 | 151 | /* Column */ 152 | .preview-body .column-wrap { 153 | margin: 1rem 0; 154 | display: flex; 155 | flex-wrap: nowrap; 156 | border: 1px solid #ccc; 157 | } 158 | .preview-body .column-wrap .column-item { 159 | padding: .5rem; 160 | flex: 1; 161 | } 162 | .preview-body .column-wrap .paragraph-wrap.align-left .images, 163 | .preview-body .column-wrap .paragraph-wrap.align-right .images { 164 | width: 60%; 165 | } 166 | 167 | /* Visual Editor */ 168 | .preview-body .ve-bold, 169 | .BEV-block-editor .ve-bold { 170 | font-weight: bold; 171 | } 172 | .preview-body .ve-highlight, 173 | .BEV-block-editor .ve-highlight { 174 | background-color: yellow; 175 | } 176 | .preview-body .ve-underline, 177 | .BEV-block-editor .ve-underline { 178 | text-decoration: underline; 179 | } 180 | .preview-body .ve-red, 181 | .BEV-block-editor .ve-red { 182 | color: red; 183 | } 184 | .preview-body .ve-blue, 185 | .BEV-block-editor .ve-blue { 186 | color: blue; 187 | } 188 | .preview-body .ve-green, 189 | .BEV-block-editor .ve-green { 190 | color: green; 191 | } -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/takitakit/block-editor-vue/73b10634ec9dab2bab2cc9714515f8e84a014034/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | 11 | block-editor-vue 12 | 13 | 14 |
15 |
16 | <% if (NODE_ENV === 'production') { %> 17 | 18 | <% } else if (NODE_ENV === 'development') { %> 19 | 20 | <% } %> 21 |
22 |
23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /public/js/development.js: -------------------------------------------------------------------------------- 1 | let options 2 | const merge_cell = { content: 'merged cell', header: true, rowspan: 3, colspan: 3 }; 3 | const merge_cell2 = { content: 'merged cell2', header: true, rowspan: 1, colspan: 2 }; 4 | const items = [ 5 | { 6 | name: 'Heading', 7 | className: 'title', 8 | level: 'h2', 9 | content: 'hoge' 10 | }, 11 | { 12 | name: 'Table', 13 | rows: [ 14 | { 15 | cells: [ 16 | { content: 'C1-1', header: true }, 17 | { content: 'C1-2', header: true }, 18 | { content: 'C1-3', header: true }, 19 | merge_cell2, 20 | { dummy: true, content: '', ref: merge_cell2 } 21 | ] 22 | }, 23 | { 24 | cells: [ 25 | { content: 'C2-1', header: false }, 26 | merge_cell, 27 | { content: '', dummy: true, ref: merge_cell }, 28 | { content: '', dummy: true, ref: merge_cell }, 29 | { content: 'C2-5' } 30 | ] 31 | }, 32 | { 33 | cells: [ 34 | { content: 'C3-1', header: false }, 35 | { content: '', dummy: true, ref: merge_cell }, 36 | { content: '', dummy: true, ref: merge_cell }, 37 | { content: '', dummy: true, ref: merge_cell }, 38 | { content: 'C3-5' } 39 | ] 40 | }, 41 | { 42 | cells: [ 43 | { content: 'C4-1', header: false }, 44 | { content: '', dummy: true, ref: merge_cell }, 45 | { content: '', dummy: true, ref: merge_cell }, 46 | { content: '', dummy: true, ref: merge_cell }, 47 | { content: 'C4-5' } 48 | ] 49 | }, 50 | { 51 | cells: [ 52 | { content: 'C5-1', header: false }, 53 | { content: 'C5-2', header: false }, 54 | { content: 'C5-3', header: false }, 55 | { content: 'C5-4', header: false }, 56 | { content: 'C5-5', header: false } 57 | ] 58 | } 59 | ], 60 | colgroup: [ 61 | { width: null }, 62 | { width: null }, 63 | { width: null }, 64 | { width: null }, 65 | { width: null }, 66 | ] 67 | }, 68 | { 69 | name: 'List', 70 | // type: 'unordered', 71 | className: 'test', 72 | rows: [ 73 | { content: 'リスト1
太字テスト' }, 74 | { content: 'リスト2' }, 75 | { content: 'リスト3' }, 76 | { content: 'リスト4' } 77 | ] 78 | }, 79 | { 80 | name: 'Paragraph', 81 | imageAlign: 'left', 82 | className: 'testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttest', 83 | images: [ 84 | { src: 'https://placehold.jp/3d4070/ffffff/150x150.png', caption: 'caption1' }, 85 | { src: 'https://placehold.jp/c122cc/ffffff/300x200.png', caption: 'caption2' }, 86 | { src: 'https://placehold.jp/22cca4/ffffff/200x300.png', caption: 'caption3' } 87 | ], 88 | content: 'externalリンク文章が入ります。internalリンク太字文章が入ります。
文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。' 89 | }, 90 | { 91 | name: 'Paragraph', 92 | imageAlign: 'left', 93 | className: 'testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttest', 94 | images: [ 95 | { src: 'https://placeholds.jp/3d4070/ffffff/150x150.png', caption: 'caption1' }, 96 | { src: 'https://placehold.jp/c122cc/ffffff/300x200.png', caption: 'caption2' }, 97 | { src: 'https://placehold.jp/22cca4/ffffff/200x300.png', caption: 'caption3' } 98 | ], 99 | content: '文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。文章が入ります。' 100 | }, 101 | { 102 | name: 'Html', 103 | content: '
hoge
' 104 | }, 105 | { 106 | name: 'Column', 107 | className: 'aaaa', 108 | columns: [ 109 | { 110 | items: [ 111 | { 112 | name: 'Paragraph', 113 | imageAlign: 'left', 114 | className: 'testtesttesttesttesttesttesttest', 115 | images: [], 116 | content: '' 117 | }, 118 | { 119 | name: 'Paragraph', 120 | imageAlign: 'right', 121 | className: null, 122 | images: [], 123 | content: '' 124 | } 125 | ] 126 | }, 127 | { 128 | items: [ 129 | { name: 'Html' } 130 | ] 131 | }, 132 | { 133 | items: [ 134 | { 135 | name: 'Paragraph', 136 | imageAlign: 'left', 137 | className: null, 138 | images: [], 139 | content: '' 140 | } 141 | ] 142 | } 143 | ] 144 | }, 145 | { 146 | name: 'Column', 147 | columns: [ 148 | { items: [] }, { items: [] } 149 | ] 150 | }, 151 | { 152 | name: 'Paragraph', 153 | imageAlign: 'left', 154 | className: 'testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttest', 155 | images: [], 156 | content: '' 157 | } 158 | ]; 159 | 160 | options = { 161 | locale: 'ja', 162 | items: items, 163 | // enabledItemNames: ['Html', 'Table'], 164 | // enabledItemNamesInColumn: ['Html'], 165 | loadItemsFromInputTag: true, 166 | allowHistories: true, 167 | allowStyledText: true, 168 | allowCssClass: true, 169 | allowFileBrowser: true, 170 | // itemOrder: [ // メニュー上のアイテムの表示順序 171 | // 'Heading', 'Image', 'List', 'Table', 'Column', 'Html', 'Paragraph' 172 | // ], 173 | FileBrowser: { 174 | url: 'http://localhost:8888/elfinder/', 175 | width: '80%', 176 | height: '80%', 177 | resizable: true, 178 | }, 179 | // cssClasses: [ 180 | // 'class1', 'class2', 181 | // {class3: 'クラス3'}, {'test-class': 'テストクラス'} 182 | // ], 183 | styledTextClasses: [ 184 | 'bold', 'link', 185 | { red: '赤字' }, { blue: '青字' }, { green: '緑字' }, 186 | { underline: '下線' }, { highlight: 'ハイライト' } 187 | ], 188 | Paragraph: { 189 | allowImages: true, 190 | defaultImageAlign: 'right', 191 | dispName: 'テキスト', 192 | presets: [ 193 | { className: 'important', dispName: '重要' }, 194 | { className: 'normal', dispName: '通常' }, 195 | { imageAlign: 'center', dispName: '中央揃え画像' } 196 | ], 197 | }, 198 | List: { 199 | maxRows: 10, 200 | allowStyledText: true, 201 | presets: [ 202 | { className: 'link', type: 'unordered', dispName: 'リンクリスト' }, 203 | { type: 'unordered', dispName: '通常リスト' }, 204 | { type: 'ordered', dispName: '箇条書きリスト' } 205 | ] 206 | }, 207 | Table: { 208 | maxRow: 10, // テーブルの最大行数 209 | maxCol: 10, // テーブルの最大列数 210 | minRow: 1, // テーブルの最小行数 211 | minCol: 2, // テーブルの最小列数 212 | presets: [ 213 | { className: 'product', dispName: '商品テーブル' }, 214 | { dispName: '通常テーブル' } 215 | ] 216 | }, 217 | Heading: { 218 | levels: ['h2', 'h3', 'h4', 'h5', 'h6'], 219 | // levels: ['h3'], 220 | levelNames: { h2: '超大見出し', h3: '大見出し', h4: '中見出し', h5: '小見出し', h6: '超小見出し' }, 221 | defaultLevel: 'h3', 222 | presets: [ 223 | { className: 'title', level: 'h2', dispName: 'タイトル' }, 224 | { className: 'sub-title', level: 'h3', dispName: 'サブタイトル' } 225 | ] 226 | }, 227 | Column: { 228 | allowChangeNumColumn: true, // カラム数の変更許可 229 | defaultNumColumn: 2, // デフォルトのカラム数 230 | maxColumn: 5, // 段組の最大数 231 | minColumn: 2, // 段組の最小数 232 | presets: [ 233 | { className: 'special', dispName: '特集カラム' }, 234 | { className: 'normal', dispName: '通常カラム' } 235 | ] 236 | }, 237 | onLoad: function (html) { 238 | updatePreview(html); 239 | }, 240 | onUpdate: function (html) { 241 | updatePreview(html); 242 | } 243 | }; 244 | const instance = new BlockEditor('#app1', options); 245 | 246 | // Update preview 247 | var previewBody; 248 | function updatePreview(html) { 249 | if (previewBody) { 250 | previewBody.innerHTML = html; 251 | } else { 252 | launchPreview(html); 253 | previewBody = document.querySelector('#preview'); 254 | } 255 | } 256 | 257 | // Preview window 258 | function launchPreview (html) { 259 | var jsFrame = new JSFrame({ 260 | horizontalAlign: 'left', 261 | verticalAlign: 'top', 262 | }); 263 | var frame = jsFrame.create({ 264 | title: 'Preview', 265 | left: 200, top: 200, width: 600, height: 400, minWidth: 300, minHeight: 200, 266 | appearanceName: 'material', 267 | appearanceParam: { 268 | border: { 269 | shadow: '0px 0px 6px -3px rgba(0,0,0,0.42)', 270 | width: 1, 271 | color: 'rgba(0,0,0,.15)', 272 | radius: 4, 273 | }, 274 | titleBar: { 275 | background: 'rgba(97, 104, 111, 1.0)' 276 | } 277 | }, 278 | style: { 279 | backgroundColor: 'rgba(255,255,255,0.88)', 280 | overflow: 'auto' 281 | }, 282 | html: '
' + html + '
' 283 | }); 284 | frame.show(); 285 | 286 | frame.setControl({ 287 | maximizeButton: 'maximizeButton', 288 | demaximizeButton: 'restoreButton', 289 | minimizeButton: 'minimizeButton', 290 | deminimizeButton: 'deminimizeButton', 291 | animation: true, 292 | animationDuration: 200, 293 | }); 294 | } 295 | -------------------------------------------------------------------------------- /public/js/production.js: -------------------------------------------------------------------------------- 1 | var options 2 | var tbl_head_row = { 3 | header: true, 4 | content: 'Table content', 5 | colspan: 3 6 | } 7 | options = { 8 | items: [ 9 | { 10 | name: 'Heading', 11 | level: 'h1', 12 | content: 'Extra-big heading' 13 | }, 14 | { 15 | name: 'Heading', 16 | level: 'h2', 17 | content: 'Big heading' 18 | }, 19 | { 20 | name: 'Heading', 21 | level: 'h3', 22 | content: 'Medium heading' 23 | }, 24 | { 25 | name: 'Heading', 26 | level: 'h4', 27 | content: 'Small heading' 28 | }, 29 | { 30 | name: 'Heading', 31 | level: 'h5', 32 | content: 'Extra-small heading' 33 | }, 34 | { 35 | name: 'Heading', 36 | level: 'h6', 37 | content: 'Minimum heading' 38 | }, 39 | { 40 | name: 'Paragraph', 41 | content: 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a', 42 | }, 43 | { 44 | name: 'Paragraph', 45 | imageAlign: 'left', 46 | images: [ 47 | { src: 'https://placehold.jp/3d4070/ffffff/600x400.png?text=Dummy', 'caption': 'Dummy caption' } 48 | ], 49 | content: 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a', 50 | }, 51 | { 52 | name: 'List', 53 | type: 'unordered', 54 | rows: [ 55 | { content: 'This is the text of the list' }, 56 | { content: 'This is the text of the list' }, 57 | { content: 'This is the text of the list' } 58 | ] 59 | }, 60 | { 61 | name: 'List', 62 | type: 'ordered', 63 | rows: [ 64 | { content: 'This is the text of the list' }, 65 | { content: 'This is the text of the list' }, 66 | { content: 'This is the text of the list' } 67 | ] 68 | }, 69 | { 70 | name: 'Table', 71 | rows: [ 72 | { 73 | cells: [ 74 | tbl_head_row, 75 | { dummy: true, ref: tbl_head_row }, 76 | { dummy: true, ref: tbl_head_row } 77 | ] 78 | }, 79 | { 80 | cells: [ 81 | { 82 | header: true, 83 | content: 'header cell' 84 | }, 85 | { 86 | content: 'cell' 87 | }, 88 | { 89 | content: 'cell' 90 | } 91 | ] 92 | }, 93 | { 94 | cells: [ 95 | { 96 | header: true, 97 | content: 'header cell' 98 | }, 99 | { 100 | content: 'cell' 101 | }, 102 | { 103 | content: 'cell' 104 | } 105 | ] 106 | } 107 | ] 108 | }, 109 | { 110 | name: 'Column', 111 | columns: [ 112 | { 113 | items: [ 114 | { 115 | name: 'Heading', 116 | level: 'h3', 117 | content: 'Heading in a column' 118 | }, 119 | { 120 | name: 'Paragraph', 121 | images: [ 122 | { src: 'https://placehold.jp/3d4070/ffffff/400x300.png?text=Dummy', caption: 'Image caption' } 123 | ], 124 | content: 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo' 125 | } 126 | ] 127 | }, 128 | { 129 | items: [ 130 | { 131 | name: 'List', 132 | type: 'unoradered', 133 | rows: [ 134 | { content: 'This is the text of the list in a column' }, 135 | { content: 'This is the text of the list in a column' }, 136 | { content: 'This is the text of the list in a column' } 137 | ] 138 | } 139 | ] 140 | } 141 | ] 142 | }, 143 | { 144 | name: 'Html', 145 | content: '
Here is a raw html
' 146 | } 147 | ], 148 | loadItemsFromInputTag: false, 149 | allowStyledText: true, 150 | styledTextClasses: ['bold','link','red','green','blue'], 151 | onLoad: function (html) { 152 | updatePreview(html); 153 | }, 154 | onUpdate: function (html) { 155 | updatePreview(html); 156 | } 157 | }; 158 | new BlockEditor('#app1', options); 159 | 160 | // Update preview 161 | var previewBody; 162 | function updatePreview(html) { 163 | if (previewBody) { 164 | previewBody.innerHTML = html; 165 | } else { 166 | launchPreview(html); 167 | previewBody = document.querySelector('#preview'); 168 | } 169 | } 170 | 171 | // Preview window 172 | function launchPreview(html) { 173 | var jsFrame = new JSFrame({ 174 | horizontalAlign: 'left', 175 | verticalAlign: 'top', 176 | }); 177 | var frame = jsFrame.create({ 178 | title: 'Preview', 179 | left: 200, top: 200, width: 600, height: 400, minWidth: 300, minHeight: 200, 180 | appearanceName: 'material', 181 | appearanceParam: { 182 | border: { 183 | shadow: '0px 0px 6px -3px rgba(0,0,0,0.42)', 184 | width: 1, 185 | color: 'rgba(0,0,0,.15)', 186 | radius: 4, 187 | }, 188 | titleBar: { 189 | background: 'rgba(97, 104, 111, 1.0)' 190 | } 191 | }, 192 | style: { 193 | backgroundColor: 'rgba(255,255,255,0.88)', 194 | overflow: 'auto' 195 | }, 196 | html: '
' + html + '
' 197 | }); 198 | frame.show(); 199 | 200 | frame.setControl({ 201 | maximizeButton: 'maximizeButton', 202 | demaximizeButton: 'restoreButton', 203 | minimizeButton: 'minimizeButton', 204 | deminimizeButton: 'deminimizeButton', 205 | animation: true, 206 | animationDuration: 200, 207 | }); 208 | } 209 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/takitakit/block-editor-vue/73b10634ec9dab2bab2cc9714515f8e84a014034/screenshot.png -------------------------------------------------------------------------------- /src/components/Heading.vue: -------------------------------------------------------------------------------- 1 | 73 | 74 | 273 | 274 | -------------------------------------------------------------------------------- /src/components/Html.vue: -------------------------------------------------------------------------------- 1 |