-
Notifications
You must be signed in to change notification settings - Fork 152
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Card/Renderer unification RFC #228
Comments
Another possible suggestion:
let card = {
name: 'some-card',
dom(buffer, ...) { ...; buffer.push(myInnerCardDOMNode); },
text(buffer, ...) { ...; buffer.push('this is the card text'); },
html(buffer, ...) { ...; buffer.push('<h2>I am a card</h2>'); },
editor: {
display(buffer, options, env, payload) {
// show the "What-You-See" part of WYSIWYG for this card
// show "edit" button, "remove" button, etc.
},
edit(buffer, options, env, payload) {
// show edit options ("save" button, "add image from disk" button, "remove" button, etc.)
},
teardown(returnFromDisplayOrEdit) {
// remove event listeners, etc
}
}
} |
Yeah, there is a lot here to hash out, probably best done in person.
I'm not as sure this is true. Display mode cards, like Ember components, need teardown as well before rendering the edit mode (or just when destroying the editor instance). |
|
@mixonic I think we're in agreement. Cards will only be removed from an edit surface (by Another thing to think about is what community-created/shared cards would look like. If each of them had to implement all the hooks for all possible render contexts they could get fairly complicated and bloated (for example, to render a card in dom client-side it would be wasteful to ship a card with a lot of unrelated html/editor/text rendering code).
@gdub22 Are you suggesting the renderer would detect what type of thing was returned and do the appropriate thing with it? (i.e., detect an array, assume it's an array of dom nodes, append each dom node, etc). Eliminating |
Right, but they need two teardowns. One for edit mode, and one for display. A proposed structure you had above seemed to share the teardown for both modes. I'm not sure I agree with the basic idea that no other env requires teardown anyway. On Bustle, if you are looking at a post and leave the page you may want to do teardown (like remove yourself from a list of Ember components) when changing pages. |
|
+1 for separate edit renderers @dtetto, makes a lot of sense. |
Completely separate renderers makes a lot of sense, I don't see the text card renderer sharing much/any code with the DOM version. Even if they did happen to be used within the same app they'd be in entirely separate contexts. |
I'm not sure what this means, but it spooks me a little. Separate npm packages? A "card" is not much of a useful abstraction if it means you must publish 5 npm packages.
I challenge this. Only the listicle items are always in "edit" mode. The other cards leverage edit/display. |
Being separate wouldn't mean it couldn't / shouldn't be distributed in the same package. Regardless of whether a card implemented all the hooks in one object vs types being separate objects, we'd make different versions with the same name to be used in different situations. Eg I don't need text rendering in my frontend, but 100% need that on the backend so we can store the text in ElasticSearch. I wouldn't want that to be in the same object because I wouldn't want to distribute it with our Ember app. Ideally when ember-cli supports tree-shaking we could keep it all in the same node package and only pay for the bits we import. Likewise we would most likely have multiple versions of HTML cards too, as we may render a card differently when including in an HTML email than we would rendering as the HTML for a PDF. |
Some notes from a discussion with Cory. First on packaging:
Regarding hooks:
Taking a couple ideas from this, we think a minimal card would look like: // package: mdc-youtube-dom
export default {
name: 'youtube',
type: 'dom',
render(fragment, options, env, payload) {
let element = document.createElement('div');
let player = new JQueryPlayer(element, payload.src);
fragment.appendChild(element);
}
} // package: mdc-youtube-dom
export default {
name: 'youtube',
type: 'dom', // the renderer using this card can assert it is the correct type
render(fragment, options, env, payload) {
let element = document.createElement('div');
let player = new JQueryPlayer(element, payload.src);
fragment.appendChild(element);
return () => { // returning a function takes the place of teardown hooks
player.destroy();
};
},
edit(fragment, options, env, payload) {
fragment.innerHTML = "Man I don't implement no edit mode!!";
},
} |
My mistake. It looks like this is also true of the |
The core challenge @bantic and I discussed is that node runtime dependencies are not platform specific. So, given that I have a text renderer that uses a node module which has C bindings, I cannot use anything from that package in webpack without including that dep in my build. Even if I don't require the dependency for the part of the package I use, I must include the dependency. Thus in our above summary we talk about allowing the package name to optionally include the "media", or alternatively have it in a file path. If the This is pretty in the weeds- and we should not explain it this way to newcomers. They should just have a set of conventions to follow.
Even tree-shaking does not apply to deps. And we also need the ecosystem to be webpack-friendly. |
Managing that state on your own is not trivial- For example @ZeeJab and I whipped up a quick card for flower today, and not needing to build the state for editing/display was a great boost to productivity. Today, you can use a card in |
One more item is that the way cards are passed to the mobiledoc kit and to renderers is different due to premature optimization. It should always be the same (an array, I suggest). |
Let's also change all hook payloads to be objects instead of multiple ordered arguments. |
I've distilled feedback from here and put together a more formal RFC/checklist in #234. |
Existing methods and inconsistencies
We now have published, quasi-official renderers for dom, html and text
When rendering cards, these renders have different expectations for named hooks that contain
setup
andteardown
methods:"display"
and"edit"
"html"
"text"
Since the DOM renderer is used both by the editor (to render cards in either "display" or "edit" mode on the editor surface) and for display-only environment (i.e., rendering cards that are displayed to a user reading an article on a site), the
display#setup
hook has special semantics for inferring its rendering environment based on the presence of anedit
property in theenv
argument tosetup()
:Another inconsistency is in the way the
setup
method works for the different renderers:element
buffer
element
buffer.push(string)
repeatedly to add HTML strings to the outputsetup
is unused)Suggestions for unification
display
hook todom
so that it matches the name of its rendering contexteditor-display
andeditor-edit
) or add a more expressive property to the env likecontext
orisInEditor
that a card can use to determine whether to show editor-specific UI (instead of inferring from the presence ofenv.edit
)setup
: I propose abuffer
object that only has a single methodpush
. In dom rendering scenarios, for each node you wanted to append to the card you'd callbuffer.push(node)
. In html rendering scenarios you'dpush
a string of HTML. In text-rendering scenarios you'dpush
a string of text.feedback welcome @mixonic @rlivsey
The text was updated successfully, but these errors were encountered: