SubtleCrypto and documenting dictionaries

I’m working on improving the SubtleCrypto docs, and had a question. The API defines a number of methods: sign(), encrypt() and so on, that take an algorithm argument. This is (typically) a dictionary object, and the contents of the object differs according to the algorithm chosen. For example:

  • if you want to encrypt with AES-CTR you need to supply an object containing {name, counter, length} (in the spec this is called an AesCtrParams object)

  • if you want to encrypt with AES-GCM you need to supply an object containing {name, iv, additionalData, tagLength} (in the spec this is called an AesGcmParams object).

There are quite a few of these objects:

// sign/verify
Algorithm {name}
RsaPssParams {name, saltLength}
EcdsaParams {name, hash}

// encrypt/decrypt/wrapKey/unwrapKey
RsaOaepParams {name, label?}
AesCtrParams {name, counter, length}
AesCbcParams {name, iv}
AesGcmParams {name, iv, additionalData, tagLength}

// generateKey
RsaHashedKeyGenParams {name, modulusLength, publicExponent, hash}
EcKeyGenParams {name, namedCurve}
HmacKeyGenParams {name, hash, length?}
AesKeyGenParams {name, length}

// deriveKey/deriveBits
EcdhKeyDeriveParams {name, public}
HkdfParams {name, hash, salt, info}
Pbkdf2Params {name, salt, iterations, hash}

// importKey
RsaHashedImportParams {name, hash}
EcKeyImportParams {name, namedCurve}
HmacImportParams {name, hash, length}

Also, the properties of these dictionaries have constraints: for example hash is a string that must be one of various values, and tagLength must be 0-128.

So the documentation for the algorithm argument, in all these methods, can get quite complex. The SubtleCrypto docs seem to deal with this inconsistently.

  • Sometimes they list the different objects inline, as in the page for encrypt(). This is a problem because it’s duplicated (the objects listed there are used in three other methods) but also because it’s cramped and hard to read, even though it omits important details.

  • Sometimes, as in the page for sign() it just says algorithm “is an object” without saying what its properties are at all, which seems terribly unhelpful.

What I would like to do is have a single page for each of these dictionary objects where I can properly describe the properties and constraints on them in one place, then link to them from the method page, like:

Questions: what “sort of page” is this AesCtrParams page? It seems like a “dictionary” (as opposed to “event”, “method”, property") page. Are there good examples of other docs that follow this pattern, that I ought to try to follow?

I know Sheppy previously brought this up, but IIUC his suggestion was to model “dictionary” pages after interface pages, which seems like overkill (i.e. to have a separate page for AesGcmParams.iv). I don’t think we should do that. But I couldn’t find any documentation for a page like this, for example at https://developer.mozilla.org/en-US/docs/MDN/Contribute/Structures/Page_types#API_reference_subpage.

We never used to document dictionaries as separate pages or page trees, as it wasn’t seen as necessary, but we’ve had more instances recently come up of dictionaries that are fairly complex and reused by multiple methods/constructors.

I recently documented this, which I am fairly happy with, and is based on an interface page:

I would love to brainstorm what a standard dictionary page needs, and then add a template to the page types section. I don’t think anyone will seriously disagree with my structure in the page above, which I believe is similar to what sheppy did anyway for his dictionary docs.

I think the only thing in question is whether we should do subpages for each property or not. I rather like subpages, as I think it is nice to be able to link to a page for exactly that property, but I don’t feel that strongly about it, and would be happy to go with a consensus.

To make things quicker, I wrote one property page and then copied everything across for all the others, including using the {{page}} macro to just copy the Examples section across.

Thanks Chris.

I think the only thing in question is whether we should do subpages for each property or not. I rather like subpages, as I think it is nice to be able to link to a page for exactly that property, but I don’t feel that strongly about it, and would be happy to go with a consensus.

Having a separate page for each property seems to make for a lot of boilerplate - lots of wrapping for a very small present. For instance in https://developer.mozilla.org/en-US/docs/Web/API/ScrollToOptions/top, the only thing that’s not also in https://developer.mozilla.org/en-US/docs/Web/API/ScrollToOptions/ is the fact that it is a double (and this could easily be incorporated into the main page). The rest is duplicated from the main page.

To make things quicker, I wrote one property page and then copied everything across for all the others, including using the {{page}} macro to just copy the Examples section across.

I think this isn’t so much about more work to create the pages - creating pages is quick - but about usability and maintainability. Someone who wants to learn about ScrollToOptions has to visit 4 pages instead of 1, and has to pick through three pages that mostly duplicate content in the first, to check that there isn’t any other extra content in there.

The other thing - and I appreciate this is difficult with ScrollToOptions, because it’s used in different APIs - is that I’d much rather keep the documentation for, say, AesCtrParams under the SubtleCrypto tree. Otherwise if you navigate from, say, encrypt() to AesCtrParams, you lose all the context (such as the sidebar and breadcrumbs).

Perhaps this sort of thing is what Sheppy is trying to address in https://github.com/mdn/kumascript/pull/738? I confess I don’t really understand APIRef though.

But even then, pretending dictionaries are interfaces seems likely to create problems. For example, https://developer.mozilla.org/en-US/docs/Web/API (not the most useful page, I know) now lists ScrollToOptions as an interface. I don’t know how many other bits of MDN assume that things under https://developer.mozilla.org/en-US/docs/Web/API are interfaces too. But creating all 17 SubtleCrypto param dictionaries under there seems likely to be misleading.

WebExtensions have a similar thing: APIs can define objects that can be used by multiple methods, for complex parameters and stuff like that. For that we have “Types”. For example, tabs.Tab. These are all listed in their own “Types” section of the main API page. Something like this seems to me like a more usable approach here in terms of the reader’s experience.

2 Likes

Someone who wants to learn about ScrollToOptions has to visit 4 pages instead of 1, and has to pick through three pages that mostly duplicate content in the first, to check that there isn’t any other extra content in there.

I think this is the killer argument right here. So basically, the Dictionary template should look similar to the Interface template, except that we don’t have separate pages for the properties.

I’d much rather keep the documentation for, say, AesCtrParams under the SubtleCrypto tree. Otherwise if you navigate from, say, encrypt() to AesCtrParams , you lose all the context (such as the sidebar and breadcrumbs).

This is handled by APIRef and GroupData. You make sure the sidebar provides that context. This is a workable solution for a dictionary that exists in the same API as the methods that use it, which will be the case most of the time. ScrollToOptions is a bit of a funny case — the CSSOM View spec is full of utility bits that are used in other places, and shouldn’t be considered anything like a normal case.

Perhaps this sort of thing is what Sheppy is trying to address in https://github.com/mdn/kumascript/pull/738?

Yes, that’s exactly it — this PR will make it so that dictionaries, types, etc. appear in their own part of the sidebar, and not under interfaces. He just needs to get the tests working to be able to add this. In addition to this, on Interface landing pages we’d put dictionaries under their own separate “Dictionaries” heading, and not under “Interfaces”. This is another template change I probably ought to make.

But even then, pretending dictionaries are interfaces seems likely to create problems. For example, https://developer.mozilla.org/en-US/docs/Web/API (not the most useful page, I know) now lists ScrollToOptions as an interface.

Yup, this is another problem that needs fixing. We’d probably want to update the {{APIListAlpha}} macro to put dictionaries in the right places, etc.

These are all listed in their own “Types” section of the main API page . Something like this seems to me like a more usable approach here in terms of the reader’s experience.

Aye, exactly what I’d like to do for dictionaries and types on regular interfaces.

2 Likes

So, my feeling is that we should have the subpages for each individual member of a dictionary, but should transclude them (or at least their “Value” section) into the overview page. That lets the overview page be fully useful, but still have the subpages for linking purposes, so that the reflexive {{domxref(“DictionaryName.member”)}} will work.

1 Like