Commits

Anonymous committed cd996f6 Draft

.

Comments (0)

Files changed (11)

doc/planning/leebre_release.md

+
+
+Outline:
+
+1. When we go to edit mode for a author asset:
+    * Show toolbar that has two buttons:
+        * One to select an asset (AssetManager dialog)
+        * Two to customize its appearance (AssetEditor dialog)
+        * Hardcode author dimensions for now
+2. Hardcode into Cover Style editor these same two buttons
+3. Fix Cover Styles
+    * change to new grammar, comment out pixtastic stuff
+    * finish image renderer for cover
+    * finish image renderer for author
+4. All the small things
+    * Fix HTML export for all elements
+    * Fix edit mode for all elements
+5. New features:
+    * PUBLISHING: a link to the help dialog on the toolbar in lieu of the
+      edit toolbar.  Fill out help info on all meta data
+    * Allow wide page mode, since narrow page can be dorky
+
+-----
+
+This document is a quick TODO for what is broken before we can release the
+editor on Leebre.org
+
+
+Major:
+
+* Asset manager: must be able to select & crop images
+
+* Rendering
+    * All the book render options should work
+        * Including:
+            * Printers Ornament,
+            * Scene breaks (do we have this yet?)
+            * Footnotes (counters?)
+            * Endnotes
+            * Verse
+            * Block quote
+    * Cover render should work (convert old styles)
+        * Does not need to support fx
+
+* Cover rendering: must render to image, etc
+
+Backend:
+
+* Make image upload work
+
+* Get nvm set up on server to run node 10 (or install node 0.10 globally, maybe
+  via ppa or something)
+
+New features:
+
+* While filling out meta-data, create a link to the help dialog on the toolbar
+  in lieu of the edit toolbar. Fill out help info on all meta data.
+
+* Allow wide page mode, since narrow page is dorky
+
+Minor bugs:
+
+* For some reason selecting book publishing style twice it will break
+
+* Impossible to insert stuff at top of document (insert toolbar does not appear)
+
+* Meta data:
+    * Meta data that is broken: Content Warning, Genre, 
+    * Meta data shows editing toolbar
+    * Enter twice when editing BIO / summary will create new paragraph
+
+-------
+
+Features to put off:
+
+* Image effects (BW, glow, etc)
+
+* Inserting images in documents
+
+
+-------
+
+
+QA spec for editor:
+
+
+1. Standard usage: Pretend you are an author new to the software.
+    * Go through the entire flow of pasting in a new book, editing mistakes,
+      and publishing it.
+    * Write down all things that didnt make sense or were broken.
+
+2. Coverage: Create a (small) test book and make sure every feature works.
+    * Try adding every single element type (ie Prologue, Epilogue, Foreword,
+      etc). Make sure adding & editing every type works as expected
+    * Publish book. Go through again and make sure every element was rendered
+      as expected.
+
+3. Platform:
+    * Abbreviated version of #1, just test pasting in book, editing, and
+      publishing.
+    * Test on Linux / Windows 7 / Windows 8
+    * Test on Firefox / Chromium / Internet Explorer (less important)
+

doc/planning/misc_projects

 
+Knuth's line-breaking algorithm done in JS YES YES YES:
+http://www.bramstein.com/projects/typeset/
+
+Super gorgeous! Could be used to output PDF line-breaking as good as LaTeX.
+
+
+-----------------
 LDT: does the transparent textarea / display layer idea in a modular fashion.
 Could be forked to allow for markdown-esque highlighting while in Edit mode.
 https://github.com/kueblc/LDT/

doc/planning/module_system_design.md

 New idea
 =====
 
-
+NOTE: see tag_design.md for the massive tag design cleanup.
 
 Plugin system could be developed independently and released as separate
 JS file. As such:

doc/planning/plan.md

 v 0.6.0 (Leebre release)
 -------
 
-* Get current features working (editing, book export)
+* Get current features working (editing, book export) (see leebre_release.md)
 
 * Work with `django-sembook` and `django-leebrary`
 
 * Plug-ins can be compiled into main JS by specifying them in build.js using
   require.js shims
 
+* MISC features:
+    * Re-add image effects, to asset manager
+    * Inserting images
+    * Image preview / rendering system:
+        *  Presently just hacking to get to work, need to do correctly with
+           extendable asset manager that can embed SVG, etc. Probably will be
+           clear how to do this in the context of the plugin systme
+
 
 
 v 1.0.0 (Desktop release)

doc/planning/tag_design.md

+Tag design
+===============
+
+(Depends on module system design & fix pseudosembook, probably should do all
+three of these in separate branch.)
+
+Currently, the concepts of tags are all over the place. Lets DRY it up!
+
+
+RULES:
+    * Every tag is either 'block', 'style', or 'static'
+        * When you click on a 'block' level tag you go into edit mode for it
+            * Example: pagraph
+        * 'style' refers to ones that are inlined within an edit mode.
+            * Every style:
+            * Example: strong, emphasis, footnote, line
+        * 'static' are un-editable and can never be deleted conventionally
+            * Example: sembook, documentmeta, cover_style
+        * NOTE: 'style' is more of a convention,  'style' is technically a subset of
+          'static' since clicking on style does not  go into edit.
+
+    * Tags have a single 'class' (for now, maybe later allow multiple
+      classes)
+
+    * Tags can inherit properties from tag-classes (i guess --- for
+      shorthand)
+
+    * Tags can contain classes: all tags of that class can be contained
+
+    * Two concepts of "block" level:
+        * Standard: click on a block level element to go into edit
+
+        * "click_target" means that you have to click on a certain selector
+          to go into edit mode for that tag.
+            * Example: Editing a chapter can only be done by clicking on
+              chapter header
+
+    * Normal mode:
+        * Tags can specify suggested CSS for normal mode
+        * Tags can also specify a function to convert to normal (for
+          complicated things)
+
+    * Edit mode:
+        * (inherited) Normal data style
+            * Automatically pops up toolbar with styling options, etc
+        * Custom: 
+            * Tags can specify arbitrary toolbars to pop-up while in edit
+              mode (generally inherited)
+        * Very custom:
+            * Just its own function that takes in a tags data in
+              htmlsembook and outputs anything necessary for editing.
+            * This function is also given a function that should be called to
+              return to normal mode.
+            * (Read these 3 styles bottom to top, ie the top most is built on
+              the others)
+
+
+LANGUAGES:
+
+Three document formats:
+    * Sembook
+        * Core \t based language for hierarchical node-based document.
+
+    * Sembook Markup
+        * Markdown / LaTeX inspired markup language, used while in edit mode,
+          or even by itself. Translates directly into Sembook format.
+        * While in edit mode, after every keypress checks to see if new
+          block-level elements have been created.
+            * The typical case for this is a new paragraph (ie, enter enter).
+            * Another case might be markup for a list or something (ie *
+              Okay\n\n*Another thing), or even a chapter marker (==New
+              chapter==).
+            * If a new blocklevel element is created it does the whole
+              splitting system that is already in place.
+        * By default all have LaTeX style \tagname{ } markups, but can also
+          have markdown-style shorthands too.
+
+    * htmlsembook
+        * pseudosembook replacement, used only by editor
+        * Explained in format redesign, essentially everything except for
+          class (tagname) and data-sb is ignored, and anything that is not a
+          <b /> is ignored. Example:
+                <b class="-sb -sb-para">
+                    <b class="-sb -sb-tr" data-sb="There once was a...">
+                        <!-- visual representation -->
+                        There once was a...
+                    </b>
+                </b>
+

js/editor/dialog/asset_edit.js

 
     AssetEdit.prototype = new Dialog();
 
-    AssetEdit.prototype.preshow = function (assetinfo) {
-        // Clear list of previously uploaded files
+    AssetEdit.prototype.preshow = function (assetinfo, asset_opts) {
         this.$controls.html('<h3>Edit</h3>');
-        this.$controls.append(this.build_controls(assetinfo));
-        var preview_html = style_asset.generate_html(assetinfo);
+        this.$controls.append(this.build_controls(assetinfo, asset_opts));
+        var preview_html = style_asset.generate_html(assetinfo, asset_otps);
         this.$preview.html('<h3>Preview</h3>');
         this.$preview.append(preview_html);
     };
 
-    AssetEdit.prototype.update_preview = function (assetinfo) {
-    };
+    AssetEdit.prototype.build_controls = function (assetinfo) {
 
-    AssetEdit.prototype.build_controls = function (assetinfo) {
         var $d = $("<img>");
+
+        var p_w = 100;
+        var p_h = 100;
+        var t_w = 500;
+        var t_h = 370;
+
+        var aspect_ratio = asset_opts.w / asset_opts.h;
+        var show_preview = _.bind(function (coords) {
+                var rx = p_w / coords.w;
+                var ry = p_h / coords.h;
+                this.$preview.css({
+                    width: Math.round(rx * t_w) + 'px',
+                    height: Math.round(ry * t_h) + 'px',
+                    marginLeft: '-' + Math.round(rx * coords.x) + 'px',
+                    marginTop: '-' + Math.round(ry * coords.y) + 'px'
+                });
+            }, this);
+
         $d.attr("src", assetinfo.url);
         $d.css('width', '250');
         //$d.imgAreaSelect({ //handles: true, //onSelectEnd: _.bind(this.update_preview, this) });
-        $d.Jcrop();
-        console.log("IMG ARES SELEDTED BITCHES");
+        $d.Jcrop({
+                aspectRatio: aspect_ratio
+            });
+        console.log("jcrop activated");
         return $d;
     };
 

js/editor/dialog/assetmanager.js

         this.reset_list();
     };
 
-    AssetManager.prototype.preshow = function (assetid) {
+    var asset_options = {
+        book: {
+            height: 701,
+            width: 433
+        },
+        author: {
+            height: 400,
+            width: 400
+        }
+    };
+
+    AssetManager.prototype.preshow = function ($edit, taginfo) {
         // Clear list of previously uploaded files
+
+        if (!$edit) {
+            // If we are in the context of a particular element
+            var asset_opts = null;
+        } else {
+            // TODO temp until we unify this system a bit more
+            if ($edit.parents('.sem.author')) {
+                var asset_opts = asset_options['author'];
+            } else {
+                var asset_opts = asset_options['book'];
+            }
+        }
+
         this.fineuploader.clearStoredFiles();
-        this.reset_list();
+        this.reset_list(asset_opts);
     };
 
 
         this.reset_list();
     };
 
-    AssetManager.prototype.reset_list = function () {
+    AssetManager.prototype.reset_list = function (asset_opts) {
         var assets = this.editor.get_assets();
 
         var $outer = $("<div>");
         for (var i in assets) {
             var asset_info = assets[i];
             console.log("asset_info", asset_info);
-            $outer.append(this.make_asset_item(asset_info));
+            $outer.append(this.make_asset_item(asset_info, asset_opts));
         }
 
         this.$trash_target = $('<div>').addClass('sbe-trash')
             });
     };
 
-    AssetManager.prototype.make_asset_item = function (item) {
+    AssetManager.prototype.make_asset_item = function (item, asset_opts) {
         var me = this;
         var thumbnail = $('<img style="width: 100px">').attr('src', item.url);
         var $t = $('<a>').attr("href", "javascript: void(0)")
                     revert: true,
                     zIndex: 100,
                     attachTo: 100
-                })
-                .click(function () {
-                    me.open(item);
                 });
 
+        // If we can select it then have that be an option
+        if (asset_opts) {
+            $t.click(function () {
+                me.open(item, asset_opts);
+            });
+        }
+
         $t.on('dragstart', function () {
             me.show_drag_options(item);
         });
         return $t;
     };
 
-    AssetManager.prototype.open = function (info) {
+    AssetManager.prototype.open = function (info, asset_opts) {
         // Put in Asset editor cropping & effect options here, large modal
-        // dialog, FUCKIN EY :)
         console.log("opening", info.id);
-        this.editor.dialogs.asset_edit.show(info);
+        this.editor.dialogs.asset_edit.show(info, asset_opts);
     };
 
     AssetManager.prototype.show_drag_options = function (info) {

js/editor/editor.js

                         prepend: opts.main_toolbar_opts.prepend
                     }),
             statistics: new toolbars.Statistics(this),
+            asset_options: new toolbars.AssetOptions(this),
             empty_document: new toolbars.EmptyDocument(this, {
                         info: opts.empty_document_info,
                         dialogs: this.dialogs })
             // No id? Create a new text object on the backend.
             this.backend.create(info.title, function (data) {
                 if (!data.id) {
+                    console.error("Could not save new document. (new id blank)");
+                    console.error("TODO make this fail");
+                    data.id = 1;
+                }
+                if (!data.id) {
                     throw "Could not save new document. (new id blank)";
                 } else {
                     me.document_info.id = data.id;
         return assets;
     };
 
+    Editor.prototype.get_asset = function (id_or_path) {
+        var assets = this.get_assets();
+        if (assets[id_or_path]) {
+            return assets[id_or_path];
+        }
+        for (var id in assets) {
+            var asset = assets[id];
+            if (asset.path === id_or_path || asset.assetid === id_or_path) {
+                return asset;
+            }
+        }
+        return null;
+    };
+
     Editor.prototype.remove_asset_from_list = function (assetid) {
         var removed = false;
         this.$content.find('.sem.assets').find('.sem.asset').each(function () {

js/editor/taghelpers.js

  * #########################################
  */
 
-
 define([
             'format/spec',
             'format/value_choices',
                         .replace('%(label)s', $s.text() || '')
                         .replace('%(value)s', $s.attr('value') || ''))
         }
-
         ,
         /* ***********************
         * formatting.
         },
         assetinstance: {
             to_edit: function (tag, $e) {
-                return $e.clone();
+               return $e.clone();
             }
             ,
             to_normal : function (tag, $e, editor) {
                 // TODO Figure out a way that this will be consistently correct
                 // during sembook -> pseudosembook conversions
+
                 var $cloned = $e.clone();
 
                 // first trim away nonsem so we only have the tags actual value
 
                 var assetid = _.str.strip($cloned.text());
 
-                var assets = editor.get_assets();
+                //var assets = editor.get_asset();
+                var assets = editor.get_asset(assetid);
 
                 // Awesome we've found the asset
                 asset = assets[assetid];
+                console.log("THESE ARE ASSETS", assetid, assets);
 
-                var html = asset_style.generate_html(asset);
+                return $('<div class="sem assetid">').css({
+                        backgroundImage: asset.url
+                    }).text(asset.assetid);
+
+                //var html = asset_style.generate_html(asset);
 
                 return $(tag.normal.replace('%(text)s', html));
             }
             normal: '<div class="sem %(tag)s"></div>'
             ,
             after_to_edit: function (editor, $edit, $elem, taginfo) {
+                var $cloned = $e.clone();
+
+                // first trim away nonsem so we only have the tags actual value
+                $cloned.find('nonsem').remove();
+
+                var assetid = _.str.strip($cloned.text());
+ 
                 // Figure out the precise taginfo here
-                editor.dialogs.assetmanager.show($edit, taginfo);
+                editor.dialogs.assetmanager.show($edit, taginfo, assetid);
             }
         },
         meta: {

js/editor/toolbar/asset_options.js

+/* #########################################
+ * license: AGPL3.0
+ * author: Michael Bethencourt
+ * copyright:  2013
+ * #########################################
+ */
+
+define(['editor/toolbar/toolbar', 'format/spec'], function (Toolbar, spec) {
+    var AssetOptions = function (editor, edit_mode) {
+        this.name = "stylepicker";
+        var options = {
+            orientation: "horizontal",
+            position: {
+                corner: "n",
+                margin: 10
+            }/*,
+            css: {
+                width: 150
+            }*/
+        };
+        Toolbar.call(this, editor, options);
+
+        this.add_buttons([
+            {
+                name: "choose",
+                title: "Choose an image from this document's assets, or upload one now.",
+                icon: "ui-icon-image",
+                //'class': "no-background"
+            }
+            ,
+            {
+                name: "crop",
+                title: "Crop and customize the currently selected image.",
+                icon: "ui-icon-scissors",
+                //'class': "no-background"
+            }
+        ]);
+
+    };
+
+    AssetOptions.prototype = new Toolbar();
+
+    AssetOptions.prototype.prehide = function () {
+    };
+
+    AssetOptions.prototype.preshow = function ($edit, $elem, taginfo) {
+        //this.$e.find('.sbe-style-name, h1').hide();
+        //this.$e.find('.' + this.get_type_class(taginfo.tagname)).show();
+        //var classes = $(context).attr('class').split(' ');
+        //return sembook.spec.search_list_for_tag(classes);
+    };
+
+    return AssetOptions;
+});

js/editor/toolbar/main.js

                     return document.URL.indexOf(s) != -1;
                 };
                 if (u("autogoto=publish")) {
-                    this.action_publish();
+                    this.editor.save(_.bind(function () {
+                        this.action_publish();
+                    }, this));
                 }
             }
         }, this));