Skip to content
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

Rfc/issue 570 context and theme packs #669

Merged
merged 14 commits into from
Aug 6, 2021

Conversation

thescientist13
Copy link
Member

@thescientist13 thescientist13 commented Jul 16, 2021

Related Issue

resolves #570

Summary of Changes

  1. Introduced the concept of a context Plugin type. as an Array
  2. Those template paths are then used as part of getAppTemplate and getPageTemplate in plugin-standard-html
  3. Also supports template from front matter
  4. Added test cases emulating a "theme pack" like package
  5. Created developer docs for Context plugin as well as a guide on Creating a Theme Pack
  6. Allowed for customizing default location for pages and templates from greenwood.config.js

Example Usage

module.exports = (options = {}) => [{
  type: 'context',
  name: 'my-theme-pack:context',
  provider: (compilation) => {
    return {
      templates: [
        path.join(compilation.context.projectDirectory, 'node_modules/my-theme-pack/dist/layouts')
      ]
    };
  }
}];

Then in a template called layouts/title.html you can "share" a template like so

<html>

  <head>
    <script type="module" src="/node_modules/my-theme-pack/dist/components/greeting.js"></script>  
  </head>

  <body>

    <h2>This is a custom page template called title from the layouts directory.</h2>
    <x-greeting></x-greeting>
    <content-outlet></content-outlet>

  </body>

</html>

Use it in frontmatter in your own workspace

---
template: 'title'
---

### Title Page

#### Some content from my own title.md page.

Even combine it with a custom app template too, using layouts/app.html

<html>

  <head>
    <link rel="stylesheet" href="/node_modules/my-theme-pack/dist/styles/theme.css"></link>
  </head>

  <body>
    <h1>This is a custom app template from the custom layouts directory.</h1>
    <page-outlet></page-outlet>
  </body>

</html>

Greenwood will automatically handle all the node resolution for that JS and CSS!!! 🏆 🙌

TODO

  1. Add example of using components (footer / header) - using ResourceInterface?
    • don't even need a ResourceInterface, just point everything to node_modules and Greenwood will take care of the rest! Brings up another question though... 👇
  2. How to resolve these files for development though, where they will not be in node_modules? 🤔
  3. Should we suggest using require.resolve for finding the right node levels directory, a la leverage NodeJS resolve logic for looking up location of paths for node modules #557
    • I think as long as users use /node_modules/<package_name> convention, and Greenwood uses require.resolve correctly, then users can depend on Greenwood doing all the heavy lifting, which makes sense for such a fundamental mechanism like resolve node_modules.
  4. Should make sure we can override a page, like an index.html so users can provide a complete "interface" as part of their theme pack
  5. Address discussion points
    • add a greenwood.config.js option for context for overriding templates and pages dir (nice to have, might make separate issue) - implemented!
    • additional input formats (array vs. string) - not needed at this time
    • use an interface? - doesn't seem warranted
    • helpful utils for plugin authors? - defer to the discussion and until we have a little more experience building these - Improve the developer experience for theme pack / context plugins #682
    • best practices / naming conventions for users - I think by virtue of having to have a unique package name on npm anyway, there would be automatic namespacing?
  6. Update documentation
  7. Create a guide for creating a "theme pack"

Discussion

  1. I think we should we support being able to specifically configure pages and templates directory from greenwood.config.js as well. The plugin approach is likely going to be more applicable to plugin authors, but for users, a "direct" configuration option, should they need it, seems best, so they can easily rename pages/ or templates/ directory name if they want to (without having to write a plugin just to do that)
    • well, one thing I realize now with pages is that those actually need to be pushed onto the graph and resolved. Greenwood scans all pages first to build, so basically we also would need to incorporate [RFC] External Data (Graph) Sources #21 as well. Since getting templates in is already a good start, I think we can / should at least merge what we have and make a new issue tracking support for pages via context and link to [RFC] External Data (Graph) Sources #21 and maybe they can both be done together?
  2. Further API considerations
    • should we support more than just pages and templates?
    • should everything just be an array
    • should we have an interface
  3. Documentation
    • encourage namespacing for template and file names?

@thescientist13 thescientist13 added the RFC Proposal and changes to workflows, architecture, APIs, etc label Jul 16, 2021
@thescientist13 thescientist13 self-assigned this Jul 16, 2021
@thescientist13 thescientist13 added CLI discussion tied to an ongoing discussion or meeting notes documentation Greenwood specific docs Plugins Greenwood Plugins enhancement Improve something existing (e.g. no docs, new APIs, etc) labels Jul 16, 2021
@thescientist13 thescientist13 mentioned this pull request Jul 24, 2021
5 tasks
@thescientist13
Copy link
Member Author

Development v Publishing

So a couple thoughts here around handling developing a theme pack vs. distributing a theme pack since the location and paths of files would be different when develop (e.g. src/some/path/) as opposed to where they will ultimately be published to (e.g. /path/to/node_modules/< package-name >/dist/etc).

I think we can establish a couple ground rules here

  1. Greenwood is likely going to be used (or will want to be used) in a development capacity by the plugin author (naturally)
  2. Paths in templates should ideally not have to change from one context to the other if so (e.g. always assume node_modules/ in <script> or <link> tags)

In other words, it's probably a bit easier to bend Greenwood to make it easier for local development in a one-off fashion for a plugin author, rather than forcing them to have jump through a bunch of hoops or extra build steps when wanting to publish their templates. Ideally when everything looks good, then can just publish everything as is and it will "just work". 🤞 ™️

So here are my thoughts 👇

Templates Location

Least hackiest approach I could think of right now is simply to have the theme pack plugin accept a secret __isDevelopment only flag for the plugin author to use, such that special logic (using npm ls <dep-name> can be determined from a greenwood.config.js to tell if the plugin is installed or not, and use that to determine the route location for files.

Example

// _greenwood.config.js_
const packageName = require('./package.json').name;
const myThemePackPlugin = require('./theme-pack-context-plugin');
const { spawnSync } = require('child_process');
const ls = spawnSync('npm', ['ls', packageName]);

module.exports = {
  plugins: [
    ...myThemePackPlugin({
      __isDevelopment: ls.stdout.toString().indexOf('(empty)') >= 0
    }]
};
// in the theme pack plugin
const path = require('path');

module.exports = (options = {}) => [{
  type: 'context',
  name: 'my-theme-pack:context',
  provider: (compilation) => {
    const { context } = compilation;
    const templateLocation = options.__isDevelopment // eslint-disable-line no-underscore-dangle
      ? path.join(process.cwd(), 'src/layouts')
      : path.join(context.projectDirectory, 'node_modules/my-theme-pack/dist/layouts');

    return {
      templates: [
        templateLocation
      ]
    };
  }
}];

Paths in Templates

For paths in templates, e.g.

<!DOCTYPE html>
<html lang="en" prefix="og:http://ogp.me/ns#">

  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <link rel="stylesheet" href="/node_modules/my-theme-pack/dist/styles/theme.css"></link>
  </head>

  <body>
    <h1>This is a custom app template from the custom layouts directory.</h1>
    <page-outlet></page-outlet>
  </body>

</html>

This looks a little cleaner, we can just have plugin authors use a Resource plugin for this in their greenwood.config.js and never have to do anything in the plugin. We can even make this part of Greenwood's "standard lib".

class MyThemePackDevelopmentResource extends ResourceInterface {
  constructor(compilation, options) {
    super(compilation, options);
    this.extensions = ['*'];
  }

  async shouldResolve(url) {
    return Promise.resolve(url.indexOf('/node_modules/my-theme-pack/') >= 0);
  }

  async resolve(url) {
    return url.replace('/node_modules/my-theme-pack/dist/', path.join(process.cwd(), '/src/layout/'));
  }
}

With all that put together, and can pretty much keep the actual code the same, and still develop like a regular Greenwood "end user". (using develop command)
Screen Shot 2021-07-27 at 4 54 21 PM

(so in this case, that URL doesn't actually exist 😉 )

@thescientist13 thescientist13 force-pushed the rfc/issue-570-context-and-theme-packs branch from 86a0db3 to 748a178 Compare August 3, 2021 17:14
@thescientist13 thescientist13 marked this pull request as ready for review August 3, 2021 21:52
@thescientist13 thescientist13 merged commit 4dbbd49 into master Aug 6, 2021
@thescientist13 thescientist13 deleted the rfc/issue-570-context-and-theme-packs branch August 6, 2021 15:13
@thescientist13 thescientist13 mentioned this pull request Aug 6, 2021
1 task
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLI discussion tied to an ongoing discussion or meeting notes documentation Greenwood specific docs enhancement Improve something existing (e.g. no docs, new APIs, etc) Guide Plugins Greenwood Plugins RFC Proposal and changes to workflows, architecture, APIs, etc
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Shared Workspaces and Contexts (Theme Packs)
1 participant