docusaurus icon indicating copy to clipboard operation
docusaurus copied to clipboard

Make `stylesheets` API more generalized

Open johnnyreilly opened this issue 1 year ago • 10 comments

Have you read the Contributing Guidelines on issues?

Description

In the same way as there's support for adding custom meta tags globally:

https://docusaurus.io/docs/api/themes/configuration#metadata

Could there also be support for adding custom link tags that are applied globally?

It looks like there isn't a way to do this with Docusaurus. The closest I've found is this section related to stylesheets:

https://docusaurus.io/docs/api/docusaurus-config#stylesheets

I initially thought this might work, but it doesn't as it depends upon an href tag being present. In my case, there isn't one - and it's not a stylesheet so that probably makes sense.

Imagine being able to do something like this in docusaurus.config.js:

module.exports = {
  linktags: [
     {
       rel: 'monetization',
       content: 'https://ilp.uphold.com/LwQQhXdpwxeJ',
     },
   ],
}

Has this been requested on Canny?

https://docusaurus.io/feature-requests/p/custom-link-tags-in-header

Motivation

I'm trying to add a custom link tag to the header of all the pages on my Docusaurus site. In my case I'm looking to render a web monetization link which looks like this:

<link rel="monetization" content="https://ilp.uphold.com/LwQQhXdpwxeJ" />

It looks like there isn't a way to do this with Docusaurus.

API design

See earlier

Have you tried building it?

No

Self-service

  • [X] I'd be willing to contribute this feature to Docusaurus myself.

johnnyreilly avatar Sep 05 '22 05:09 johnnyreilly

This is a very weird gotcha, but stylesheets does exactly what you want (because rel is overridable). I've spoken in multiple places that it's probably a bad (unintuitive, at least) API...

Josh-Cena avatar Sep 05 '22 05:09 Josh-Cena

So I'd hoped that stylesheets would work, but when I attempted it here it errored when I didn't supply an href:

https://github.com/johnnyreilly/blog.johnnyreilly.com/pull/277/commits/ba2e5f7c260da6015d1af1076e418ca411064ff3

This is the link I'm trying to render (no href):

<link rel="monetization" content="https://ilp.uphold.com/LwQQhXdpwxeJ" />

(Look at the docusaurus.config.js tweaks commented out)

johnnyreilly avatar Sep 05 '22 05:09 johnnyreilly

Ah, that's right. It's a validation bug, then. Frankly I don't know if we should redesign the API or just relax the validation for non-rel="stylesheet" links.

Josh-Cena avatar Sep 05 '22 05:09 Josh-Cena

I'd say that using stylesheets to configure something that very much isn't a stylesheet is very unintuitive and quite confusing. It's also not very discoverable when you're searching for config options (I almost missed it)

I'd be tempted to copy paste the metatags API in the codebase to add a new linktags API which works exactly the same way and is configured alongside the metatags API.

What do you think?

johnnyreilly avatar Sep 05 '22 07:09 johnnyreilly

Yep—agreed. I wonder how many people actually use it for stylesheets—for me it's about 40% of the time. 60% for non-CSS.

Josh-Cena avatar Sep 05 '22 15:09 Josh-Cena

What about using the plugin API?

https://docusaurus.io/docs/api/plugin-methods/lifecycle-apis#injectHtmlTags

function MySitePlugin(context, options) {
  return {
    name: 'my-site-plugin',
    injectHtmlTags({content}) {
      return {
        headTags: [
          {
            tagName: 'link',
            attributes: {
              rel: 'preconnect',
              href: 'https://www.github.com',
            },
          },
        ],
      };
    },
  };
};

I understand it's not very convenient, intuitive or even easy to discover, but it should solve the issue. I often think about creating some config shortcuts to expose these lifecycles in a friendly way. A bit like if each site always had 1 mandatory site plugin 🤷‍♂️


Yep—agreed. I wonder how many people actually use it for stylesheets—for me it's about 40% of the time. 60% for non-CSS.

Curious to know how you use it without CSS?


Note: it may be important to have a stylesheet-specific API to ensure that stylesheets are loaded in the right order and CSS specificity is predictible. For example, we may want to have link preconnect at the top, and stylesheets at the bottom of head. I'm not sure mixing those is a great idea. See also https://github.com/facebook/docusaurus/issues/3678

slorber avatar Sep 07 '22 11:09 slorber

@slorber See for example: https://github.com/typescript-eslint/typescript-eslint/blob/8176fb15299943cbf20385eb0ea7ba877e193285/packages/website/docusaurusConfig.ts#L192-L215

All that stylesheets does is to add a link tag with a default ref="stylesheet attribute. It's not exclusively for CSS.

Josh-Cena avatar Sep 07 '22 12:09 Josh-Cena

All that stylesheets does is to add a link tag with a default ref="stylesheet attribute.

I understand, I mean later we may want to do something more like ensuring the stylesheet is inserted in the bottom, and prevent such usage where you override the rel: you'd rather use another API for non-stylesheet needs

slorber avatar Sep 07 '22 14:09 slorber

That's cool for me as well, but we want something better than using plugin lifecycles. Let's just create a headTags root-level API that gets directly piped to injectHtmlTags?

Josh-Cena avatar Sep 07 '22 14:09 Josh-Cena

Just noticed this discussion here after I'd submitted my PR! I can understand the idea of special treatment for CSS given that it has a special usecase. It's probably possible to handle that with a generic API but why change it given there's already a custom one in place I guess.

I wasn't aware of the ability to use the plugin API to achieve this, so thanks for sharing! My feeling is that it does feel a kind of bruteforce way to achieve something that you might hope would exist out of the box. That said, I'm glad it exists! I've submitted a PR for sister API to the metadata one which is hopefully helpful and pretty general in approach.

johnnyreilly avatar Sep 10 '22 11:09 johnnyreilly