WIP: Project state in plugins#2979
Conversation
|
| version: 1 | ||
| project: | ||
| title: Tagged Pages Plugin Example | ||
| plugins: | ||
| - plugin.mjs | ||
| toc: | ||
| - file: index.md | ||
| - file: apples.md | ||
| - file: oranges.md | ||
| - file: bananas.md |
There was a problem hiding this comment.
Not sure if this is worth putting in here, but sometimes it is nice to jump into a specific example?
| project?: SessionProject; | ||
| }; | ||
|
|
||
| export type PluginUtils = { select: Select; selectAll: SelectAll; unstableSession: SessionAPI }; |
There was a problem hiding this comment.
This is the main change, that we pass more information to the plugins.
There was a problem hiding this comment.
so if I understand, PluginUtils now gets an extra SessionAPI object, and within that object, plugin authors can access the SessionProject, and within that they can access the SessionSite and list of SessionPage objects?
| * transforms (running in `postProcessMdast`) all pages have been processed so this | ||
| * data is complete. | ||
| */ | ||
| function getSessionProject(session: ISession, projectPath?: string): SessionProject | undefined { |
There was a problem hiding this comment.
Here we actually construct this. This function is pretty messy, and the goal is to resolve a clean API to consumers through the plugins.
choldgraf
left a comment
There was a problem hiding this comment.
This seems like a really nice start, and this would be a really useful addition for plugin authors. I linked #1616 , and added a few comments throughout.
In general, I think this looks pretty good - we should add a little bit of plugin dev docs so authors can learn more about this, and there were a few pieces that I thought would be particularly useful to add, though not critical as long as we don't close a door on them. If we don't have bandwidth for that right now, my vote would be to just get this in so we can experiment with it.
| project?: SessionProject; | ||
| }; | ||
|
|
||
| export type PluginUtils = { select: Select; selectAll: SelectAll; unstableSession: SessionAPI }; |
There was a problem hiding this comment.
so if I understand, PluginUtils now gets an extra SessionAPI object, and within that object, plugin authors can access the SessionProject, and within that they can access the SessionSite and list of SessionPage objects?
| // Load custom transform plugins | ||
| const documentSessionProject = getSessionProject(session, projectPath); |
There was a problem hiding this comment.
| // Load custom transform plugins | |
| const documentSessionProject = getSessionProject(session, projectPath); | |
| /** Document transform stage */ | |
| // Load custom transform plugins | |
| const documentSessionProject = getSessionProject(session, projectPath); |
There was a problem hiding this comment.
Just to make it clear this is document stage (I think it is?)
| const projectSessionProject = getSessionProject(session, projectPath); | ||
| session.plugins?.transforms.forEach((t) => { |
There was a problem hiding this comment.
| const projectSessionProject = getSessionProject(session, projectPath); | |
| session.plugins?.transforms.forEach((t) => { | |
| /** Project transform stage (document stage is above) */ | |
| const projectSessionProject = getSessionProject(session, projectPath); | |
| session.plugins?.transforms.forEach((t) => { |
There was a problem hiding this comment.
also not critical - just trying to make the macro-structure of this a bit easier to parse
| pipe.use(t.plugin, undefined, { | ||
| select, | ||
| selectAll, | ||
| unstableSession: { |
There was a problem hiding this comment.
Quick check: if old plugins don't include unstableSession will they break until they update? Could we ensure it's optional so this doesn't happen?
| */ | ||
| function taggedTransform(opts, utils) { | ||
| return async (mdast) => { | ||
| const { selectAll, unstableSession } = utils; |
There was a problem hiding this comment.
unstableSession feels a little idiosyncratic to me - could we try to think of a more intuitive naming for plugin authors? Based on what's inside, my brain immediately went to something like sessionContext or buildContext or something like that...I feel like the unstable could make sense, but is also a bit verbose and may not be necessary as long as we document this functionality clearly enough (ie, note that it is unstable, and that certain moments in the build chain are more unstable than others)
There was a problem hiding this comment.
I do like the explicitness of "unstable". We could also use a namespace, e.g.
utils.hazmat.session.
There was a problem hiding this comment.
I won't die on this hill if y'all like unstableFoo :-)
| * affiliations, contributors, doi, etc.) extended with the page's location | ||
| * within the site. | ||
| */ | ||
| export type SessionPage = PageFrontmatter & { |
There was a problem hiding this comment.
Does this open a pathway towards us getting the AST from the page as well? I know that here it's just frontmatter, but I think it'd be quite useful to get information in the AST from other pages. For example, that "collect abbreviations" PR that @haroldcampbell opened up (#2985 ).
| template?: string; | ||
| }; | ||
|
|
||
| /** Minimal project information exposed to plugins via the unstable session API. */ |
There was a problem hiding this comment.
why not pass the whole project config? I've seen several plugins want to have access to other config in myst.yml (though, in many cases they are defining their own config in myst.yml which might get dropped when it passes through the validator...).
I think this isn't strictly needed for this PR but want to flag it in case it is a design decision to leave open a pathway for doing this in a follow up
| unstableSession: { | ||
| page: { slug: pageSlug, frontmatter }, | ||
| project: documentSessionProject, | ||
| }, |
There was a problem hiding this comment.
Or if it's not easy to provide the AST to transforms, could we add parseMyst function to the transforms and then they could parse stuff themselves? (I think this would be useful either way)
| slug?: string; | ||
| index?: string; | ||
| title?: string; | ||
| pages: SessionPage[]; |
There was a problem hiding this comment.
I think this should be one pages[] at the top. The slug/index/title should be the first one in here.
Working in person with @stefanv on blog listing through improving the global project state that is available to plugins.
This puts more information in the global plugin (
documentphase is most reliable), and can be exposed through plugins in a bit of a simpler way. This can help support blog listings, and many other full-project views of parsed content that do not rely on parsing themdfiles independently.