analogjs / analog

The fullstack meta-framework for Angular. Powered by Vite and Nitro
https://analogjs.org
MIT License
2.59k stars 250 forks source link

fix(vite-plugin-angular): allow supplying and exporting vfile data for agx files #1344

Closed joshuamorony closed 2 months ago

joshuamorony commented 2 months ago

I've taken the liberty of experimenting with a solution for this, so of course feel free to disregard if the approach/API isn't appropriate. Happy to make changes as required too.

Currently with agx files the frontmatter export is created before the markdown template transforms run, which is fine, but when the transform functions run they might want to add vfile data (as is the case with some remark/rehype plugins e.g. I have created some plugins that track word count/headings through vfile data)

At the moment when a markdown template transform is run it might return all the data as a vfile, e.g:

VFile {
  cwd: '/Users/joshuamorony/Dev/projects/oss/analog-stuff',
  data: {},
  history: [],
  messages: [],
  value: '<h2>Test</h2>\n' +
    '<p>Hello</p>\n' +
    '<ul>\n' +
    '<li>one</li>\n' +
    '<li>two</li>\n' +
    '<li>three</li>\n' +
    '</ul>\n' +
    '<ul>\n' +
    '<li>one</li>\n' +
    '<li>two</li>\n' +
    '<li>three</li>\n' +
    '</ul>'
}

But then the rest of the data needs to be dropped to be compatible with the markdown template transform format, and just the value as the content string is returned, e.g:

export const agxRemarkRehype =
  (options: RemarkRehypeOptions = {}): MarkdownTemplateTransform =>
  async (content: string) => {
    const processor = setupUnified(options);

    // Contains all the vFile data
    const mdContent = await processor.process(content);

    // Contains only the value string from the vFile data
    return String(mdContent);
  };

So all of the vfile data, including any data plugins might have added, will be lost. Currently there is no way to add metadata to the resulting content (e.g. through markdown transform/plugins), only the original frontmatter defined in the file will make it through when actually using the agx component.

e.g. given this plugin set up:

markdownTemplateTransforms: [
  agxRemarkRehype({
    remarkPlugins: [
      [preview, { percentage: 0.4 }],
      getHeadings,
      getWordCount,
    ],
    rehypePlugins: [rehypeSlug, rehypePrettyCode],
  }),
],

Everything works just as it does in the svx ecosystem, except getHeadings and getWordCount because they don't actually transform the AST, they just create metadata about the tree via the VFile.

What is the new behavior?

This PR allows the markdown template transforms to optionally return a vfile instead of a content string. A vfile defines its own internal toString method that can be used to retrieve the normal content string, but now we also have a way to make any additional metadata available.

The existing markdown transform loop will now use the content string directly as normal if just a string is supplied, but if a vfile is supplied it will invoke the vfiles toString method to get the transformed content.

But the markdown template transforms are now also being run a second time, in order to generate the vfile data at the same time that the metadata export is created for the agx file. If any vfile data is returned it is added to an additional vfile export.

This way you would be able to access any vfile metadata data along with the frontmatter metadata when using agx files.

UPDATE: To make the vfile data easier to access with the existing injectContent approach, I modified this to instead merge the vfile data into the metadata export instead of making it its own export. This means with the existing injectContent functionality you can just access the vfile data through attributes.vfile.

Example attributes for standard transform that returns a string

Screenshot 2024-09-16 at 12 07 06 pm

Example attributes for transform that returns a vfile

Screenshot 2024-09-16 at 12 09 36 pm

Does this PR introduce a breaking change?

No, although technically on the off chance that someone happened to already be naming one of their front matter properties vfile this update would cause that property to be overwritten

Other information

[optional] What gif best describes this PR or how it makes you feel?

netlify[bot] commented 2 months ago

Deploy Preview for analog-ng-app ready!

Name Link
Latest commit e7e18eca118213345cd7d3fb804c32a331366cee
Latest deploy log https://app.netlify.com/sites/analog-ng-app/deploys/66ea16604f57b20008c28ab1
Deploy Preview https://deploy-preview-1344--analog-ng-app.netlify.app
Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

netlify[bot] commented 2 months ago

Deploy Preview for analog-blog ready!

Name Link
Latest commit e7e18eca118213345cd7d3fb804c32a331366cee
Latest deploy log https://app.netlify.com/sites/analog-blog/deploys/66ea16607f9194000821f904
Deploy Preview https://deploy-preview-1344--analog-blog.netlify.app
Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

netlify[bot] commented 2 months ago

Deploy Preview for analog-app ready!

Name Link
Latest commit e7e18eca118213345cd7d3fb804c32a331366cee
Latest deploy log https://app.netlify.com/sites/analog-app/deploys/66ea1660b1871d0008fe72f2
Deploy Preview https://deploy-preview-1344--analog-app.netlify.app
Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

netlify[bot] commented 2 months ago

Deploy Preview for analog-docs ready!

Name Link
Latest commit e7e18eca118213345cd7d3fb804c32a331366cee
Latest deploy log https://app.netlify.com/sites/analog-docs/deploys/66ea16606079250008f7b3b7
Deploy Preview https://deploy-preview-1344--analog-docs.netlify.app
Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

joshuamorony commented 2 months ago

Note: I updated the PR to instead merge the VFile data with the existing metadata export so that it can more easily be accessed through the existing injectContent functionality