w3c / reffy

Reffy is a Web spec crawler and analyzer tool. It is notably used to update Webref
MIT License
70 stars 23 forks source link

CSS types only defined and extracted as values #1146

Open cdoublev opened 1 year ago

cdoublev commented 1 year ago

Since this change (I think), <timeline-name> is not extracted as a type but only as a value namespaced under <single-animation-timeline>. The HTML markup looks like this:

<dl>
  <dt>
    <dfn data-dfn-for="<single-animation-timeline>" data-dfn-type="value">
      <a data-link-type="type">
        &lt;timeline-name>
      </a>
    </dfn>
  </dt>
  <dd>
    <pre class="prod">&lt;timeline-name> = &lt;custom-ident> | &lt;string></pre>
  </dd>
</dl>

I think a type should always be defined as a "global" value, then a rule/property/descriptor/type can restrict or contextualize its definition.

However I do not think it should be the responsibility of Reffy to provide this guarantee, and the above markup looks wrong to me. I would like to get your opinion before asking for a fix on w3c/csswg-drafts.

EDIT: <timeline-name> has been replaced by <custom-ident>, which is a well defined terminal / CSS basic type, but the root problem remains, ie. a type should be defined at least once as a type.

tidoust commented 1 year ago

I think a type should always be defined as a "global" value, then a rule/property/descriptor/type can restrict or contextualize its definition.

Global and local definitions are conceptually correct but the main problem is probably the lack of consistency across specs, making it harder to process the data. That heterogeneity is likely a simple result of there being different spec authors (who approach definitions with slightly different mental models), and of this likely being seen as low priority in any case. If it becomes clear that a global (or local) approach is the way to go, we could envision curating the data in Reffy.

To start with, I think it would be useful to list values (and specs) that look like types or functions and that don't have corresponding global type or function definitions. Do you have that at hand by any chance? I'll explore the data otherwise.

A side question is whether definitions that have a data-dfn-type equal to type or function can also have a data-dfn-for attribute. I think that there are some occurrences of that in the extracts.

tidoust commented 1 year ago

To start with, I think it would be useful to list values (and specs) that look like types or functions and that don't have corresponding global type or function definitions

A quick look at data yields the following list of types and functions that don't have a global definition (number of occurrences is the number of occurrences as value in the extract, not in the spec):

cdoublev commented 1 year ago

I was wrong, sorry: it is fine that a type is declared only under a namespace.

A side question is whether definitions that have a data-dfn-type equal to type or function can also have a data-dfn-for attribute.

The problem is that <timeline-name> is only ever defined with data-dfn-type equal to value, with its production rule wrapped in the corresponding <dd>. Maybe the spec author should add data-dfn-type=type on its <dfn> to supersede data-dfn-type=value on the parent <dl>?

Restricting the search to values whose name looks like a type but are never defined as such, I only have the following results (excluding <timeline-name>):

Yes. I also agree that it is likely being seen as low priority in any case.

I was thinking that adding some templates in the Bikeshed documentation, that spec authors could refer to, may help a bit. Ideally, the existing specs should be correct and such templates would not be needed.

tidoust commented 1 year ago

I don't know what the correct way of defining CSS things should be, but if the argument is that there should always be an underlying type definition of a value when it is actually a type, I think that the same should apply for functions. Completing your list with function-like values that are only defined as value yields:

On top of these, there are at least a couple of places where things look a bit clunky:

I was thinking that adding some templates in the Bikeshed documentation, that spec authors could refer to, may help a bit. Ideally, the existing specs should be correct and such templates would not be needed.

Always a good idea to add more documentation for spec authors. Pull requests that improve the documentation would most likely be well received :)

For what it's worth, the definitions data model currently embedded in Bikeshed's documentation is also followed by ReSpec (even though ReSpec's documentation currently says that only dfn and idl are supported) and the editing tool that powers the HTML spec. With a few exceptions. We tried to move the model to a separate document and converge on a single model some time ago, see https://github.com/speced/spec-dfn-contract. That did not go very far for lack of a dedicated editor.

cdoublev commented 1 year ago

[...] if the argument is that there should always be an underlying type definition of a value when it is actually a type, I think that the same should apply for functions

I do not think so. Here is my understanding, removing any I think and ignoring that you may already agree with some of these statements.

foo() can be defined as foo() = foo(<length>) for a property distance, and as foo() = foo(<time>) for a property duration. foo() must be defined with <dfn dfn-type="value"> in both property definitions. It must never be defined with <dfn dfn-type="function">, and it cannot be referenced as <foo()>.

When the syntax of foo() is not context-sensitive and is used in different context, it must be defined with <dfn dfn-type="type"> and it can be referenced as <foo()>. Some property may define it with <dfn dfn-type="value"> to provide some specific (context-sensitive) parsing or serialization rules in prose, or some context to interpret the result from parsing.

These cases are examples where a template may be usefull.

Thanks for giving me some context on this.

tidoust commented 1 year ago

When the syntax of foo() is not context-sensitive and is used in different context, it must be defined with <dfn dfn-type="type"> and it can be referenced as <foo()>

Did you mean dfn-type="function" or are you intentionally suggesting to get rid of function as a definition type?

foo() can be defined as foo() = foo(<length>) for a property distance, and as foo() = foo(<time>) for a property duration. foo() must be defined with <dfn dfn-type="value"> in both property definitions. It must never be defined with <dfn dfn-type="function">, and it cannot be referenced as <foo()>.

That would work. That said, as with selectors, I'm personally interested in foo being exposed as a function directly because all developers are going to understand foo(<length>) as "calling function foo with a length as parameter", and some people will want to document or talk about foo as a function as a result. Hiding it as a value does not help. Whether the meaning foo depends on the underlying property is orthogonal.

The fact that such functions sometimes appear using a functional notation (<foo()>) coupled with a real function definition, and sometimes directly as a combination of keyword, literals and type references (foo(<length>) does not help either.

One example where this affected MDN pages for the fit-content() function page is described in https://github.com/mdn/content/issues/18780#issuecomment-1216912692

Also, having functions directly at hand makes it easier to build or validate pages such as the CSS Functional index.

As usual, the CSS Working Group would be the right place to go to suggest changes. The approaches mentioned above or the hybrid model currently followed by CSS specs all more or less work as far as I can tell. Re-constructing the list of functions automatically from values is not too hard in particular.

cdoublev commented 1 year ago

Yes, I meantfunction, and I totally agree with the rest.

cdoublev commented 1 year ago

Fwiw, css-module seems to be a CSS-specific template. It does not include an example of a function namespaced under a property, a type namespaced under a function, a rule, a type defined in a definition list of values, etc.

Maybe we can discuss the examples it might include in another issue, before making a PR? Or you can do this without me. I am just offering my help if you do not want or do not have time to do it.

tidoust commented 1 year ago

It's a good idea to crystallize guidelines in the css-module template. Your help is definitely welcome! I indeed don't think I'll have much time to do that. Feel free to engage with the CSS WG directly and/or to list the different cases in an issue here beforehand!

I also note that I don't exactly know what to suggest in corner cases. For instance, I didn't address the definition of <wcag2> in CSS Color 6 to expose a function after all, because I realized I did not really know what to recommend. The wcag2 value and the wcag2() functional notation are scoped to contrast-color(). The function would be useless in any other context so that makes sense to me. That said, the wcag2() function appears in <wcag2> which, as a "type" in the global namespace. It does not make sense to me to reference a scoped definition from a global definition (that would make the scoped definition part of the global namespace). In the end, I don't really know what markup to suggest.