Writing Components
This page explains how MarkBind components work, focused on implementation and testing.
MarkBind provides a number of components (e.g. expandable panels, tooltips) to dynamically express content. In order to serve content on the browser, MarkBind syntax is converted to valid HTML.
There are multiple ways to implement MarkBind components.
One way to implement a MarkBind component is to transform the node itself. This is a more low-level implementation that can be useful when a node only needs to be modified slightly.
When a node is processed, MarkBind syntax is converted to HTML, and any remaining attributes will also be converted to HTML attributes. This can be useful if you just need to add a HTML attribute to the node, or modify the value of an existing attribute.
These transformations may take place at various stages of node processing: before (preProcessNode
), during (processNode
), or after (postProcessNode
).
Examples
Many MarkBind components are implemented as Vue components, either by creating a component in the vue-components
package, or by importing a component from an external library.
This can be useful when a more complicated set of features is needed, where a Vue component can provide an interface for us to manage these functionalities.
Vue components are registered in vue-components/src/index.js
, which allows them to be used in the template section of any Vue instance without needing to be imported first.
Examples
MarkBind components can be implemented as a plugin as well.
This is suitable for more lightweight components where the implementation is largely in processing the node, making it fitting to use MarkBind plugins' processNode
or postRender
interfaces.
These interfaces provide additional entry points for modifying the page generated, and do not replace MarkBind's usual node processing.
The Writing Plugins page is a good guide to get started on plugins.
Examples
tree
component is implemented as a default pluginAutomated tests that are relevant to the components include:
The API for Snapshot tests can be found at Vue Test Utils.
Additionally, it's a good idea to check the deployed PR preview in addition to serving the app locally, to ensure that there are no differences.
Some things you may need to consider when implementing a MarkBind component:
Reactivity refers to the ability of a web framework to update your view whenever the application state has changed. It is important to consider reactivity when implementing a component that may have dynamic contents that readers can interact with (e.g. opening a panel, triggering a tooltip to show).
Components should be compatible with SSR (Server-Side Rendering). Minimally, there should be no SSR issues (viewable from the browser console), though a lack of warnings does not mean that there are no SSR problems. A guide on SSR for MarkBind can be found here.
Vue-specific tips for resolving SSR issues:
mount
and beforeMount
lifecycle hooks will only be executed on the client, not the serverv-if
, ensure that it will evaluate to the same value on both the client and serverWhen creating a new component, you may need to import a package or library to support some functionality. Ideally, this should not increase MarkBind's bundle size too much. Bundlephobia may be useful to quickly look up the size of a package!
When choosing to use a third-party library or package, it should ideally be well-maintained and not have too many dependencies. While dependencies may be inevitable, a package with dependencies on large libraries may lag behind the most recent releases of these libraries, which may become a blocker for MarkBind to migrate to these recent releases as well.
For instance, if bootstrap-vue
depends on Bootstrap and Vue, we will need to wait for bootstrap-vue
to migrate to the newest versions of both Bootstrap and Vue before MarkBind can migrate to these versions of Bootstrap and Vue as well.
Feel free to raise any concerns during the initial discussion phase for other devs to weigh in on the tradeoffs!
MarkBind components may support , or both. Some components allow users to supply the same content as either a slot or an attribute. If an author provides the same content as both a slot and an attribute, in most cases, the slot should override the attribute.
MarkBind should also log a warning to inform the author of this conflict!