]> BookStack Code Mirror - bookstack/commitdiff
Modularised/bundled js and made image-manager a proper component
authorDan Brown <redacted>
Thu, 8 Oct 2015 22:49:18 +0000 (23:49 +0100)
committerDan Brown <redacted>
Thu, 8 Oct 2015 22:49:18 +0000 (23:49 +0100)
21 files changed:
bower.json
gulpfile.js
package.json
resources/assets/js/components/image-manager.vue [new file with mode: 0644]
resources/assets/js/components/image-picker.vue [new file with mode: 0644]
resources/assets/js/global.js
resources/assets/js/image-manager.js [deleted file]
resources/assets/js/jquery-extensions.js
resources/assets/js/pages/book-show.js
resources/assets/js/templates/image-picker.html [deleted file]
resources/assets/sass/_header.scss
resources/assets/sass/styles.scss
resources/views/base.blade.php
resources/views/books/delete.blade.php
resources/views/chapters/delete.blade.php
resources/views/pages/create.blade.php
resources/views/pages/delete.blade.php
resources/views/pages/edit.blade.php
resources/views/pages/form.blade.php
resources/views/pages/image-manager.blade.php [deleted file]
resources/views/settings/index.blade.php

index 5d991b0f22b9d7d663582d520fc1fe273f9ec8ce..06bed0478eff6bbc3627fdf068be44b760fbb376 100644 (file)
     "tests"
   ],
   "dependencies": {
-    "dropzone": "~4.0.1",
     "tinymce-dist": "~4.2.1",
     "bootstrap": "~3.3.5",
     "jquery-sortable": "~0.9.13",
-    "material-design-iconic-font": "~2.1.1",
-    "vue": "~0.12.10",
-    "vue-resource": "~0.1.15"
+    "material-design-iconic-font": "~2.1.1"
   }
 }
index 7974350d147c52772f98bc3a87f9db0b186cac08..b7f680a831a73d9e7bd9252011d404bfbd1692eb 100644 (file)
@@ -1,8 +1,11 @@
 var elixir = require('laravel-elixir');
 
+elixir.config.js.browserify.transformers.push({
+    name: 'vueify',
+    options: {}
+});
 
 elixir(function(mix) {
     mix.sass('styles.scss');
-    mix.scripts('image-manager.js', 'public/js/image-manager.js');
-    mix.browserify(['jquery-extensions.js', 'pages/book-show.js' ,'global.js'], 'public/js/common.js');
+    mix.browserify(['jquery-extensions.js', 'global.js'], 'public/js/common.js');
 });
index 5106741e3cf514543012b421d27d84a28efddd75..af40e256ff617343d499c000b7ea89f0b9c528c9 100644 (file)
@@ -3,11 +3,14 @@
   "devDependencies": {
     "gulp": "^3.8.8",
     "insert-css": "^0.2.0",
-    "laravel-elixir-livereload": "1.1.3"
+    "laravel-elixir-livereload": "1.1.3",
+    "vueify": "^1.1.5"
   },
   "dependencies": {
     "bootstrap-sass": "^3.0.0",
+    "dropzone": "^4.0.1",
     "laravel-elixir": "^3.3.1",
-    "vue": "^0.12.16"
+    "vue": "^0.12.16",
+    "vue-resource": "^0.1.16"
   }
 }
diff --git a/resources/assets/js/components/image-manager.vue b/resources/assets/js/components/image-manager.vue
new file mode 100644 (file)
index 0000000..d489768
--- /dev/null
@@ -0,0 +1,192 @@
+<template>
+    <div id="image-manager">
+        <div class="overlay" v-el="overlay" v-on="click: overlayClick" >
+            <div class="image-manager-body">
+                <div class="image-manager-content">
+                    <div class="image-manager-list">
+                        <div v-repeat="image: images">
+                            <img class="anim fadeIn"
+                                 v-class="selected: (image==selectedImage)"
+                                 v-attr="src: image.thumbnail, alt: image.name, title: image.name"
+                                 v-on="click: imageClick(image)"
+                                 v-style="animation-delay: ($index > 26) ? '160ms' : ($index * 25) + 'ms'">
+                        </div>
+                        <div class="load-more" v-show="hasMore" v-on="click: fetchData">Load More</div>
+                    </div>
+                </div>
+                <button class="neg button image-manager-close" v-on="click: hide()">x</button>
+                <div class="image-manager-sidebar">
+                    <h2 v-el="imageTitle">Images</h2>
+                    <hr class="even">
+                    <div class="dropzone-container" v-el="dropZone">
+                        <div class="dz-message">Drop files or click here to upload</div>
+                    </div>
+                    <div class="image-manager-details anim fadeIn" v-show="selectedImage">
+                        <hr class="even">
+                        <form v-on="submit: saveImageDetails" v-el="imageForm">
+                            <div class="form-group">
+                                <label for="name">Image Name</label>
+                                <input type="text" id="name" name="name" v-model="selectedImage.name">
+                            </div>
+                        </form>
+                        <hr class="even">
+                        <div v-show="dependantPages">
+                            <p class="text-neg text-small">
+                                This image is used in the pages below, Click delete again to confirm you want to delete this image.
+                            </p>
+                            <ul class="text-neg">
+                                <li v-repeat="page: dependantPages">
+                                    <a v-attr="href: page.url" target="_blank" class="text-neg">@{{ page.name }}</a>
+                                </li>
+                            </ul>
+                        </div>
+
+                        <form v-on="submit: deleteImage" v-el="imageDeleteForm">
+                            <button class="button neg"><i class="zmdi zmdi-delete"></i>Delete Image</button>
+                        </form>
+                    </div>
+                    <div class="image-manager-bottom">
+                        <button class="button pos anim fadeIn" v-show="selectedImage" v-on="click:selectButtonClick"><i class="zmdi zmdi-square-right"></i>Select Image</button>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<script>
+
+    var Dropzone = require('dropzone');
+
+    module.exports = {
+        data: function(){
+            return {
+                images: [],
+                hasMore: false,
+                page: 0,
+                cClickTime: 0,
+                selectedImage: false,
+                dependantPages: false,
+                deleteForm: {},
+                token: document.querySelector('meta[name=token]').getAttribute('content')
+            }
+        },
+
+        created: function () {
+            // Get initial images
+            this.fetchData(this.page);
+            window.ImageManager = this;
+        },
+
+        ready: function () {
+            // Create dropzone
+            this.setupDropZone();
+        },
+
+        methods: {
+            fetchData: function () {
+                var _this = this;
+                this.$http.get('/images/all/' + _this.page, function (data) {
+                    _this.images = _this.images.concat(data.images);
+                    _this.hasMore = data.hasMore;
+                    _this.page++;
+                });
+            },
+
+            setupDropZone: function () {
+                var _this = this;
+                var dropZone = new Dropzone(_this.$$.dropZone, {
+                    url: '/upload/image',
+                    init: function () {
+                        var dz = this;
+                        this.on("sending", function (file, xhr, data) {
+                            data.append("_token", _this.token);
+                        });
+                        this.on("success", function (file, data) {
+                            _this.images.unshift(data);
+                            $(file.previewElement).fadeOut(400, function () {
+                                dz.removeFile(file);
+                            });
+                        });
+                    }
+                });
+            },
+
+            imageClick: function (image) {
+                var dblClickTime = 380;
+                var cTime = (new Date()).getTime();
+                var timeDiff = cTime - this.cClickTime;
+                if (this.cClickTime !== 0 && timeDiff < dblClickTime && this.selectedImage === image) {
+                    // DoubleClick
+                    if (this.callback) {
+                        this.callback(image);
+                    }
+                    this.hide();
+                } else {
+                    this.selectedImage = (this.selectedImage === image) ? false : image;
+                    this.dependantPages = false;
+                }
+                this.cClickTime = cTime;
+            },
+
+            selectButtonClick: function () {
+                if (this.callback) {
+                    this.callback(this.selectedImage);
+                }
+                this.hide();
+            },
+
+            show: function (callback) {
+                this.callback = callback;
+                this.$$.overlay.style.display = 'block';
+            },
+
+            overlayClick: function (e) {
+                if (e.target.className === 'overlay') {
+                    this.hide();
+                }
+            },
+
+            hide: function () {
+                this.$$.overlay.style.display = 'none';
+            },
+
+            saveImageDetails: function (e) {
+                e.preventDefault();
+                var _this = this;
+                _this.selectedImage._token = _this.token;
+                var form = $(_this.$$.imageForm);
+                $.ajax('/images/update/' + _this.selectedImage.id, {
+                    method: 'PUT',
+                    data: _this.selectedImage
+                }).done(function () {
+                    form.showSuccess('Image name updated');
+                }).fail(function (jqXHR) {
+                    form.showFailure(jqXHR.responseJSON);
+                })
+            },
+
+            deleteImage: function (e) {
+                e.preventDefault();
+                var _this = this;
+                _this.deleteForm.force = _this.dependantPages !== false;
+                _this.deleteForm._token = _this.token;
+                $.ajax('/images/' + _this.selectedImage.id, {
+                    method: 'DELETE',
+                    data: _this.deleteForm
+                }).done(function () {
+                    _this.images.splice(_this.images.indexOf(_this.selectedImage), 1);
+                    _this.selectedImage = false;
+                    $(_this.$$.imageTitle).showSuccess('Image Deleted');
+                }).fail(function(jqXHR, textStatus) {
+                    // Pages failure
+                    if(jqXHR.status === 400) {
+                        _this.dependantPages = jqXHR.responseJSON;
+                    }
+                });
+            }
+
+        }
+
+    };
+</script>
\ No newline at end of file
diff --git a/resources/assets/js/components/image-picker.vue b/resources/assets/js/components/image-picker.vue
new file mode 100644 (file)
index 0000000..fe2b1f3
--- /dev/null
@@ -0,0 +1,37 @@
+
+<template>
+    <div class="image-picker">
+        <div>
+            <img v-if="image && image !== 'none'" v-attr="src: image, class: imageClass" alt="Image Preview">
+        </div>
+        <button class="button" type="button" v-on="click: showImageManager">Select Image</button>
+        <br>
+        <button class="text-button" v-on="click: reset" type="button">Reset</button> <span class="sep">|</span> <button class="text-button neg" v-on="click: remove" type="button">Remove</button>
+        <input type="hidden" v-attr="name: name, id: name" v-model="image">
+    </div>
+</template>
+
+<script>
+    module.exports = {
+        props: ['currentImage', 'name', 'imageClass'],
+        data: function() {
+            return {
+                image: this.currentImage
+            }
+        },
+        methods: {
+            showImageManager: function(e) {
+                var _this = this;
+                ImageManager.show(function(image) {
+                    _this.image = image.url;
+                });
+            },
+            reset: function() {
+                this.image = '';
+            },
+            remove: function() {
+                this.image = 'none';
+            }
+        }
+    }
+</script>
\ No newline at end of file
index 66326da2352d9fb0edb2d0e100360f21f9635e4d..519ce74128a90ea620d542dad9efcc2ecea7d362 100644 (file)
@@ -1,9 +1,10 @@
+
+// Global jQuery Elements
 $(function () {
 
     // Notification hiding
     $('.notification').click(function () {
         $(this).fadeOut(100);
-
     });
 
     // Dropdown toggles
@@ -18,34 +19,25 @@ $(function () {
 
 });
 
+function elemExists(selector) {
+    return document.querySelector(selector) !== null;
+}
+
+// Vue JS elements
+var Vue = require('vue');
+Vue.use(require('vue-resource'));
 
 // Vue Components
+Vue.component('image-manager', require('./components/image-manager.vue'));
+Vue.component('image-picker', require('./components/image-picker.vue'));
 
-Vue.component('image-picker', {
-    template: require('./templates/image-picker.html'),
-    props: ['currentImage', 'name', 'imageClass'],
-    data: function() {
-        return {
-            image: this.currentImage
-        }
-    },
-    methods: {
-        showImageManager: function(e) {
-            var _this = this;
-            ImageManager.show(function(image) {
-                _this.image = image.url;
-            });
-        },
-        reset: function() {
-            this.image = '';
-        },
-        remove: function() {
-            this.image = 'none';
-        }
-    }
-});
+// Vue Controllers
+if(elemExists('#book-dashboard')) {
+    new Vue(require('./pages/book-show'));
+}
 
 // Global Vue Instance
+// Needs to be loaded after all components we want to use.
 var app = new Vue({
     el: '#app'
 });
\ No newline at end of file
diff --git a/resources/assets/js/image-manager.js b/resources/assets/js/image-manager.js
deleted file mode 100644 (file)
index 4433a95..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-
-
-window.ImageManager = new Vue({
-
-    el: '#image-manager',
-
-    data: {
-        images: [],
-        hasMore: false,
-        page: 0,
-        cClickTime: 0,
-        selectedImage: false,
-        dependantPages: false,
-        deleteForm: {}
-    },
-
-    created: function () {
-        // Get initial images
-        this.fetchData(this.page);
-    },
-
-    ready: function () {
-        // Create dropzone
-        this.setupDropZone();
-    },
-
-    methods: {
-        fetchData: function () {
-            var _this = this;
-            this.$http.get('/images/all/' + _this.page, function (data) {
-                _this.images = _this.images.concat(data.images);
-                _this.hasMore = data.hasMore;
-                _this.page++;
-            });
-        },
-
-        setupDropZone: function () {
-            var _this = this;
-            var dropZone = new Dropzone(_this.$$.dropZone, {
-                url: '/upload/image',
-                init: function () {
-                    var dz = this;
-                    this.on("sending", function (file, xhr, data) {
-                        data.append("_token", document.querySelector('meta[name=token]').getAttribute('content'));
-                    });
-                    this.on("success", function (file, data) {
-                        _this.images.unshift(data);
-                        $(file.previewElement).fadeOut(400, function () {
-                            dz.removeFile(file);
-                        });
-                    });
-                }
-            });
-        },
-
-        imageClick: function (image) {
-            var dblClickTime = 380;
-            var cTime = (new Date()).getTime();
-            var timeDiff = cTime - this.cClickTime;
-            if (this.cClickTime !== 0 && timeDiff < dblClickTime && this.selectedImage === image) {
-                // DoubleClick
-                if (this.callback) {
-                    this.callback(image);
-                }
-                this.hide();
-            } else {
-                this.selectedImage = (this.selectedImage === image) ? false : image;
-                this.dependantPages = false;
-            }
-            this.cClickTime = cTime;
-        },
-
-        selectButtonClick: function () {
-            if (this.callback) {
-                this.callback(this.selectedImage);
-            }
-            this.hide();
-        },
-
-        show: function (callback) {
-            this.callback = callback;
-            this.$$.overlay.style.display = 'block';
-        },
-
-        overlayClick: function (e) {
-            if (e.target.className === 'overlay') {
-                this.hide();
-            }
-        },
-
-        hide: function () {
-            this.$$.overlay.style.display = 'none';
-        },
-
-        saveImageDetails: function (e) {
-            e.preventDefault();
-            var _this = this;
-            var form = $(_this.$$.imageForm);
-            $.ajax('/images/update/' + _this.selectedImage.id, {
-                method: 'PUT',
-                data: form.serialize()
-            }).done(function () {
-                form.showSuccess('Image name updated');
-            }).fail(function (jqXHR) {
-                form.showFailure(jqXHR.responseJSON);
-            })
-        },
-
-        deleteImage: function (e) {
-            e.preventDefault();
-            var _this = this;
-            _this.deleteForm.force = _this.dependantPages !== false;
-            $.ajax('/images/' + _this.selectedImage.id, {
-                method: 'DELETE',
-                data: _this.deleteForm
-            }).done(function () {
-                _this.images.splice(_this.images.indexOf(_this.selectedImage), 1);
-                _this.selectedImage = false;
-                $(_this.$$.imageTitle).showSuccess('Image Deleted');
-            }).fail(function(jqXHR, textStatus) {
-                // Pages failure
-                if(jqXHR.status === 400) {
-                    _this.dependantPages = jqXHR.responseJSON;
-                }
-            });
-        }
-
-    }
-
-});
index bda36f5e672ad0a9f3fdfdf058ac830294cc2275..c41a721e4fed42e2641541a0c2ea631638c2a8de 100644 (file)
@@ -56,7 +56,7 @@ jQuery.fn.submitForm = function() {
 jQuery.fn.dropDown = function() {
     var container = $(this),
         menu = container.find('ul');
-    container.find('[data-dropdown-toggle]').on('click', function() {
+        container.find('[data-dropdown-toggle]').on('click', function() {
         menu.show().addClass('anim menuIn');
         container.mouseleave(function() {
             menu.hide();
index 3d5d352555ca68c98d2149ea0944048b16c39340..7388cced1b6e28181672f0d904418d92e44d5e5d 100644 (file)
@@ -1,5 +1,5 @@
 
-new Vue({
+module.exports = {
     el: '#book-dashboard',
     data: {
         searching: false,
@@ -29,4 +29,4 @@ new Vue({
             this.searchTerm = '';
         }
     }
-});
\ No newline at end of file
+};
\ No newline at end of file
diff --git a/resources/assets/js/templates/image-picker.html b/resources/assets/js/templates/image-picker.html
deleted file mode 100644 (file)
index 82f0ef7..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-
-<div class="image-picker">
-    <div>
-        <img v-if="image && image !== 'none'" v-attr="src: image, class: imageClass" alt="Image Preview">
-    </div>
-    <button class="button" type="button" v-on="click: showImageManager">Select Image</button>
-    <br>
-    <button class="text-button" v-on="click: reset" type="button">Reset</button> <span class="sep">|</span> <button class="text-button neg" v-on="click: remove" type="button">Remove</button>
-    <input type="hidden" v-attr="name: name, id: name" v-model="image">
-</div>
\ No newline at end of file
index 60a14fde80faa4da7b370f1a45bae1769b76b905..72026887aca571c3b54fe9968925211427eecb82 100644 (file)
@@ -110,7 +110,6 @@ form.search-box {
   right: 0;
   margin: $-m 0;
   background-color: #FFFFFF;
-  list-style: none;
   box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.1);
   border-radius: 1px;
   border: 1px solid #EEE;
index beea1c1b438e74f037e6f6dcbf034f951a5feedf..d652fbedcc791e026280d0783476f928195771fe 100644 (file)
@@ -15,6 +15,8 @@
 @import "lists";
 @import "pages";
 
+[v-cloak] {display: none;}
+
 // Jquery Sortable Styles
 .dragged {
   position: absolute;
index de774042ac6e170854fc325400a9ab8b245b8775..6a9da2099349ff21e5372500116c321ac097a2ba 100644 (file)
@@ -8,16 +8,13 @@
     <meta name="token" content="{{ csrf_token() }}">
 
     <!-- Styles and Fonts -->
-    <link rel="stylesheet" href="/css/app.css">
+    <link rel="stylesheet" href="/css/styles.css">
     <link href='//fonts.googleapis.com/css?family=Roboto:400,400italic,500,500italic,700,700italic,300italic,100,300' rel='stylesheet' type='text/css'>
     <link rel="stylesheet" href="/bower/material-design-iconic-font/dist/css/material-design-iconic-font.min.css">
 
     <!-- Scripts -->
     <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
     <script src="/bower/jquery-sortable/source/js/jquery-sortable.js"></script>
-    <script src="/bower/dropzone/dist/min/dropzone.min.js"></script>
-    <script src="/bower/vue/dist/vue.min.js"></script>
-    <script src="/bower/vue-resource/dist/vue-resource.min.js"></script>
 
     @yield('head')
 </head>
index ebd870234ea3410c6394bfa3afd7ac98fa5e251f..f4cf1d8d765182150aae0c548668a76096d5dab2 100644 (file)
@@ -15,8 +15,4 @@
         </form>
     </div>
 
-@stop
-
-@section('bottom')
-    @include('pages/image-manager')
 @stop
\ No newline at end of file
index 3fc3ae1dc0ed37169b71aefbd686e767fb167003..940404323f142382c4533bc1b184f90ebba472c6 100644 (file)
@@ -16,8 +16,4 @@
         </form>
     </div>
 
-@stop
-
-@section('bottom')
-    @include('pages/image-manager')
 @stop
\ No newline at end of file
index 619eadfa6433b7f9826dbe54b073379e8436b1c4..ad635b291245abb960e9d3661fc4a683196b1dd0 100644 (file)
@@ -16,9 +16,4 @@
             @endif
         </form>
     </div>
-@stop
-
-@section('bottom')
-    @include('pages/image-manager')
-    <script src="/js/image-manager.js"></script>
 @stop
\ No newline at end of file
index 4b44424c7462f1c816cd762004ca1106cd1ee272..eb93271220c61e53d185591ce9bb970491f225d1 100644 (file)
@@ -14,8 +14,4 @@
         </form>
     </div>
 
-@stop
-
-@section('bottom')
-    @include('pages/image-manager')
 @stop
\ No newline at end of file
index c69df7d0253c9a2c806cb458a6ed58e801a8c704..bf56a1495446f262abfaece5c09fa79e1f5fc827 100644 (file)
@@ -15,9 +15,4 @@
         </form>
     </div>
 
-@stop
-
-@section('bottom')
-    @include('pages/image-manager')
-    <script src="/js/image-manager.js"></script>
 @stop
\ No newline at end of file
index a35aa5abeb5c781b15d2c0d342ab95e97bffb336..44e396c840225a9364bbcf67811d367c5415ed2c 100644 (file)
@@ -98,4 +98,6 @@
 
 
     });
-</script>
\ No newline at end of file
+</script>
+
+<image-manager></image-manager>
\ No newline at end of file
diff --git a/resources/views/pages/image-manager.blade.php b/resources/views/pages/image-manager.blade.php
deleted file mode 100644 (file)
index 4e82294..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-
-<div id="image-manager">
-    <div class="overlay" v-el="overlay" v-on="click: overlayClick" >
-        <div class="image-manager-body">
-            <div class="image-manager-content">
-                <div class="image-manager-list">
-                    <div v-repeat="image: images">
-                        <img class="anim fadeIn"
-                             v-class="selected: (image==selectedImage)"
-                             v-attr="src: image.thumbnail, alt: image.name, title: image.name"
-                             v-on="click: imageClick(image)"
-                             v-style="animation-delay: ($index > 26) ? '160ms' : ($index * 25) + 'ms'">
-                    </div>
-                    <div class="load-more" v-show="hasMore" v-on="click: fetchData">Load More</div>
-                </div>
-            </div>
-            <button class="neg button image-manager-close" v-on="click: hide()">x</button>
-            <div class="image-manager-sidebar">
-                <h2 v-el="imageTitle">Images</h2>
-                <hr class="even">
-                <div class="dropzone-container" v-el="dropZone">
-                    <div class="dz-message">Drop files or click here to upload</div>
-                </div>
-                <div class="image-manager-details anim fadeIn" v-show="selectedImage">
-                    <hr class="even">
-                    <form v-on="submit: saveImageDetails" v-el="imageForm">
-                        {{ csrf_field() }}
-                        <div class="form-group">
-                            <label for="name">Image Name</label>
-                            <input type="text" id="name" name="name" v-model="selectedImage.name">
-                        </div>
-                    </form>
-                    <hr class="even">
-                    <div v-show="dependantPages">
-                        <p class="text-neg text-small">
-                            This image is used in the pages below, Click delete again to confirm you want to delete this image.
-                        </p>
-                        <ul class="text-neg">
-                            <li v-repeat="page: dependantPages">
-                                <a v-attr="href: page.url" target="_blank" class="text-neg">@{{ page.name }}</a>
-                            </li>
-                        </ul>
-                    </div>
-
-                    <form v-on="submit: deleteImage" v-el="imageDeleteForm">
-                        <input type="hidden" v-model="deleteForm._token" value="{{ csrf_token() }}">
-                        <button class="button neg"><i class="zmdi zmdi-delete"></i>Delete Image</button>
-                    </form>
-                </div>
-                <div class="image-manager-bottom">
-                    <button class="button pos anim fadeIn" v-show="selectedImage" v-on="click:selectButtonClick"><i class="zmdi zmdi-square-right"></i>Select Image</button>
-                </div>
-            </div>
-        </div>
-    </div>
-</div>
index f6ecadce0abcc43320d27784c8f50cc6da2629a7..47cfe1f307388e2044a6096187dd432b5755d2a5 100644 (file)
@@ -84,9 +84,6 @@
 
 </div>
 
-@stop
+<image-manager></image-manager>
 
-@section('bottom')
-    @include('pages/image-manager')
-    <script src="/js/image-manager.js"></script>
-@stop
\ No newline at end of file
+@stop