-
Notifications
You must be signed in to change notification settings - Fork 53
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
Proposal: First Class Shortcode Support #29
Comments
@jbmoelker and @halafi would love your thoughts here. |
👏 nice writeup! I'm really not sure what the best approach would be, I'm not a big shortcode user myself, but I have some thoughts:
I think I need to sleep on this ;) |
@jbmoelker Awesome. Thank you for your thoughts, they helped spawn some ideas I'd never considered.
Adding Shortcodes:I like the idea of a helper function, but I'm not sure what benefit it gives us over just accepting an object/array. I can see it being useful if Elder.js didn't have such a well defined bootstrap process. I'll dig into 11ty's prior art more. Naming Conflicts:
Updated Signature:I can lots of uses where we need Further giving shortcodes access to many of the same
Notes:Potential Speedup AvailableThe existing shortcode solution requires the shortcode parser to be rebuilt on each request to get the Executing ShortcodesI'm torn between offering a 'user only' hook and introducing that documentation complexity vs just offering a flag to enable/disable or provide an array of routes to run them on. Async Support?One problem is that I don't believe the current shortcode tool supports Async. Given shortcodes have access to the query object, this would make it trivial to make replaceable data point shortcode if you could make async database calls there. Empty / Undefined Shortcode ReturnWe need plan for shortcodes to return undefined and see how that impacts the current implementation. I could see that breaking it. Read Only ProxiesNot to self: We'll want all props of the shortcodes to be read only proxies. |
Shortcode support started: #35 |
Hey Elder.js users.
I want to float my current thinking on shortcodes and the plan to add them to the Elder.js core to get buy-in from early users.
Benefit: Shortcodes make static content dynamic and future proof. Elder.js should support them natively.
The Context
Whether your content lives in .md files, on Prismic, Contentful, WordPress, Strapi, your own CMS, or elsehwere, content is generally pretty static.
That said, anytime content lives in a CMS there is always a demand to add 'functionality' to this content.
In my experience thisfunctionalities come in a few flavors.
datapoint
with a real statistic. (see below)Shortcodes to solve all of these problems.
Shortcodes
If you aren't familiar with shortcodes are strings that can wrap content or have their own attributes:
{{shortcode attribute="" /}}
{{shortcode}}wraps{{/shortcode}}
NOTE: The
{{
and}}
brackets vary from system to system.1. Custom HTML Output
I'm in the process of porting my own website to Elder.js. During this process there are many times where I want a
<div class="box">content here</div>
to add design flair.To achieve these I've built a simple shortcode:
{{box}}content here{{/box}}
allowing me to change the markup as needed should my needs change in the future.2. Data With Shortcodes
A common use case for shortcodes that we've seen on ElderGuide.com and other properties that we are developing with Elder.js is the need to have an "article" with otherwise static content but that needs a datapoint from a database. (outlined above)
For example we often need to have content that would have this functionality:
The US has [numberOfNursingHomes] nursing homes nationwide.
As it currently stands we do this type of replacement within our
data
functions and have a shortcode like so:{{stat key="numberOfNursingHomes" /}}
.The Problem:
As I've extracting out functionality from our sites, I'm finding more and more cases where plugins could offer shortcodes as well.
I've also found a major need for a shortcode to embed Svelte components, but the ideal implementation doesn't exist within the current Elder.js framework.
A. Minimizing Plugin Interdependence
My initial plan was to release a shortcode plugin using hooks. The shortcode plugin would register and manage the shortcodes from other plugins.
Then if a sister plugin (say the "image plugin") wanted to offer a shortcode it would require the shortcode plugin to also be installed.
The problem with this approach is plugin interdependence.
It just doesn't feel right for a plugin to only offer 1/3 of it's functionality without another plugin installed. There is also an issue of making sure each plugin doesn't overwrite the other's functionality.
B.
data.key
replacementAnother hurdle is that in a perfect world we'd be able to do
{{svelteComponent component="Clock" props="data.key" options="{loading: "eager"}"/}}
and the clock component would be hydrated with the values found on data.key.In order to achieve this, the shortcode plugin would need the context of the
data
object returned from the route and would need to run between the generation of theroute
html and thetemplate
html.Currently there is no hook that can support this... and hooks aren't really the right solution because we only want 1 instance of the shortcode parser to run.
The Plan
Our current implementations use a fork of the https://github.com/metaplatform/meta-shortcodes library. I've used this shortcode library in one form or another since 2016. It is battle tested across my sites, allows for open and close bracket customization, but could use a modernization effort. (not the focus of this proposal)
To implement shortcodes the plan is as follows:
Page.ts
:Page.ts
after thepage.route.templateComponent
function has built the route's HTML, shortcodes would be executed on the returned HTML.page.route.layout
and page HTML generation would continue as it currently does.The benefits of this location are 3 fold:
page.route.layout
we can use Elder.js' internal system forinlineSvelteComponent
to embed arbitrary svelte components offering a solution to embed Svelte components{{svelteComponent component="Clock" /}}
.data
related hooks and functions will have executed, we know that the data object is stable and could offer the ability to pass the data context into shortcodes as well allowing for{{svelteComponent component="Clock" props="data.key"/}}
wheredata.key
would be the key taken from the data object.Defining Shortcodes:
Shortcodes could be defined in two places:
elder.config.js
for user defined shortcodes.Proposed Definition (simple)
props
are the attributes defined on the shortcode.content
is the content wrapped in the shortcode.data
is the data object.Proposed Definition (robust)
The biggest limitation to the 'simple' design is there is no access to add css, js, or elements to the
<head>
.I've hit this limitation in the past with WordPress and it was limiting, so a more complex design that would be more robust would be to support an API signature as below where
css
,js
, andhead
are all added to thestacks
needed to support them.NOTE: this requires moving where stacks are processed.
Shortcodes by Default
By default the only shortcode I'd imagine shipping is the
{{svelteComponent component="Clock" props="" options="" /}}
.This does add a small regex call that appears to add about 1.2ms per page generation time in local testing.
This is the first major feature that I'm looking at adding to the core and I'd like community feedback. I'm not sure how OSS projects usually handle this but my goal is to get buy-in from early users. If you have feedback I'd love to hear it.
Having used several static site generators, I do believe this functionality belongs in the core. One of my biggest gripes with Gatsby is that it pushes all of the customization to plugins and solves the plugin interdependence problem with "Themes." While this works for one-off projects, it doesn't allow easy copy and pasting between projects because each Gatsby project is it's own special snowflake due to plugin interdependence. I think Elder.js offering shortcodes from the core is a wise move but would love feedback and some devil's advocates on why it shouldn't be in the core.
The text was updated successfully, but these errors were encountered: