>> >> It is also entirely possible to use annotations internally, and then >> export to XML. > > That's what I had in mind: store "as close as 'internal > representation' as possible" and turn into something else only when > needed (basically, exporting to the DocBook-like XML schema) > Or maybe do the transformation before storage, but the key point is:
transformation would likely be lossy, ideally you'd want your internal storage to preserve all the original information. >> Image thumbnails pretty much do this already, except for the arbitrary >> size, but that should be simple to add. The rest is pretty much >> already implemented. > > Well, in our case, the caption shouldn't be stored in the doc, but > rather "pushed" to the domain object when modified by the user (i.e. > maybe it'll be read-only in the editor, if possible, and modified only > through, say, a "change caption" dialog box). > But of course the thumbnail doodad will provide a very good code base! so, the rendering of an image thumbnail would be a function of both the document and some external state that contains the caption? (it's already a function of the document and external state that contains the image data I suppose, but this would be pushing that further. It's ok, just clarifying). > >>> - "semantic" markup is >>> - mostly about attaching a domain-specific term/category to the >>> selected text, e.g. this is a person, date, building material, etc. >>> (there are something like 50 thesaurus/list-of-values to choose from; >>> the user "attaches" the selected text to one such thesaurus, and can >>> optionally select a specific value from the list) I don't know if >>> annotations would be the best fit here: we don't have the constraint >>> of running through several paragraphs, but it's likely that, despite >>> not spec'd, such semantic markup shouldn't overlap; so elements could >>> be used; plus, the value being optional could make it impractical to >>> distinguish "start of annotation without value" from "end of >>> annotation" (if we use the DocInitialization XML representation). >> >> annotation values are opaque strings, so you can choose to interpret >> them however you like. if a particular annotation has no value, but is >> merely a marker, then an empty string, or single letter, would suffice >> as marking it "present" (null being absent). > > OK, so you'd still go with annotations for that use case. > My last note about the possible issue with optional value was related > this comment in DocOpUtils: > // This code renders ending annotations and annotations that are > // changed to null the same way, which is OK since we are > // only concerned with DocIntializations. (It's, in fact, the > // only correct solution since our test cases use this code for > // equality comparison of documents.) I'm pretty sure that comment is either not relevant here, or not a problem for your use case. > But re-thinking about it (and looking at the client-server protocol), > annotations are probably best serialized separately, along the lines > of the Wave API's Blip object, rather than in the form of "annotation > boundaries" (like in ProtocolDocumentOperation and > DocOp/DocInitialization); or if in the form of annotation boundaries, > make sure to serialize 'null' differently than the empty string. At the end of the day it doesn't really matter how you serialize. You could use a protobuf of a doc initialization for something compact and binary; you could use the PST version to get json; you could use DocOpUtil.toXmlString to get something more xml-ish and human readable. When you render a document to a user you can present it however you like. I'm curious why you feel in particular separating annotations out is a superior strategy? The doc initialization style is pretty straight forward, it represents the document as a stream from beginning to end, rather than "two passes" of xml and then the annotations. (but again, doesn't matter really). >> not sure i understand - do you want an annotation with multiple values >> at once, or more like an enum i.e. can take on one of several possible >> values? (both doable, several strategies depending on use case >> specifics). > > Simply an enum (I was just trying to be exhaustive in listing the features). that's fine, just map each enum value to a specific string. >> perfect - you just register the right set of doodads for the features >> you want enabled. think of the editor not as an editor, but as "editor >> tools". you build your editor by composing together the bits you want. >> put all the bits in for the fully featured version, put only some bits >> for the simpler version, etc. > > Would you use different schemas too? (e.g. to handle the case of > someone pasting a table or figure in an editor where it's not allowed) Ideally, and there is a design floating around for this, you'd define little mini-schemas to go with your doodads, and you'd register them all together. Unfortunately, at the moment, the schema is a separate beast, and is defined all in one go. This is a bit annoying but not a problem for you. You define a schema for the whole document and provide it to the editor, so it's ok. >> There may be a couple of hard coded bits here and there but it's >> definitely not tightly bound, > > OK, that's good news. I think I'll stick with <line/>s until I put > everything else in place, and then iff <p>s looks more appropriate to > our use then maybe I'll try to replace <line/> (and remove the > hard-coded bits; btw, I just stumbled on a few ones in > ContentDocument#checkHealthy and debugCheckHealthy) well those are easy to fix, you can just delete them, they're basically just assertions :) (if we want to keep them we can probably put checkHealthy methods in each doodad renderer instead and have the editor call that). > >> in fact, it used to be that we had >> <p>...</p> and <h1>...</h1>, but we moved away from it for OT reasons. >> There is still some unused code in there for working with paragraphs >> (though most has been deleted). > > org.waveprotocol.wave.client.editor.content.paragraph.Paragraph is > still there, and register()ed in Editors#initRootRegistries (and used > by the form.input doodad). You're probably looking at local paragraph, which is one of those "local nodes". I think the slides explain these a bit. They're easy to spot because they have "l:" namespace, e.g. "l:p". Yes that code is actually from the original paragraph code when <p>'s were not "local nodes" (this is before open sourcing). > >>> If you could give me hints about how best to: >>> - initialize an Editor (use an "owned" ContentDocument or not? what >>> should I register in the registries?) >>> - put content into, and get content out of the editor: should I >>> rather use the "persistent document" (and if yes, which class: >>> PersistentContentDoc, ContentRawDocument? I must confess I'm lost with >>> all these classes and interfaces) or a "doc initialization"? >>> - make my own schema(s), and how to map the "structural" and >>> "semantic" markup (elements? annotations?) >>> It'd help me start customizing the editor to my needs and see what >>> could be improved to make it a standalone component (starting with >>> writing some docs! ;-) ) >> >> i don't know if these have already been migrated to confluence, but >> here's something better than nothing: >> >> http://www.waveprotocol.org/code/tutorials/writing-a-doodad >> http://www.waveprotocol.org/protocol/design-proposals/editor >> http://danilatos.com/Wave_Summit_2010_Editor.pdf (this might be >> published somewhere else properly, but i couldn't find it, so i just >> put it here for now). > > Awesome, thanks! > I came across the first two (didn't read the first one as I was first > interested in making a simple editor work and understand how to > initialize it and how it works; well, the doodad tutorial is all about getting a simple editor up and running in a few lines of code, and then extending it :) also you can look around the editor test harness code in general, it's a bit of a munge but it sets up an editor and pokes it in various interesting ways. > and forgot about the second one, which > was a bit hard to understand for me at the time) but your slides > really shade some light on the overall design! (a picture is worth a > thousand words) > >> The above should give you some idea, but a few pointers: > > Thanks a whole lot, I'll digest all of that and start coding a more > featured prototype (I got a simple editor working, with a simple > toolbar for turning bold on and off on the selection; based on the > wavepanel.impl.toolbar.EditToolbar code; this one really deserves a > bit of work to make it less "wave-centric" and a bit pluggable) > great! looking forward to seeing it.
