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

feat(macros): rewrite CSSSyntax macro #4656

Merged
merged 37 commits into from
Jun 23, 2022
Merged

Conversation

wbamberg
Copy link
Collaborator

@wbamberg wbamberg commented Sep 11, 2021

This is a rewrite of the CSSSyntax macro, with three main changes:

1 use webref instead of mdn/data
2 use css-tree instead of a pile of regexes
3 implement basic pretty-printing and syntax highlighting

The motivation here was mostly to use webref, but it's a lot easier and safer to rewrite the macro to use css-tree than to try to modify the existing one. The extra features we could perhaps have deferred to another PR, but I thought it would be nice for this change to include something user-visible.

Things this version doesn't do that the old one did

  • this version only works with CSS properties, not selectors or at-rules. This is because webref doesn't include data for anything except properties (as far as I could see, but maybe I am wrong?) I think it's fine to limit formal syntax to properties, but we'd need to remove macro calls from unsupported pages.

  • this version doesn't have any support for l10n (except for making sure links will work). I was going to add something but it turns out that the current macro only supports "de", so dropping support doesn't seem like a regression.

  • this version doesn't include tooltips and links for combinators (e.g. "||, "|" etc), only for multipliers ("*", "?" etc). That's because css-tree doesn't give me easy access to those things. We could do some regex hackery to fix that, if it seems important.

  • this version currently doesn't include links from types, either internal links to further-down-the-formal-syntax or to dedicated pages like https://developer.mozilla.org/en-US/docs/Web/CSS/angle. This is mostly because I'd like to understand what we would like to do here. I think the internal links are not very useful but the links to external pages are - but of course we don't have pages for all types, so this implies that the macro would need a list of all the pages we have, which seems hacky and hard to maintain [Update: thinking about this some more: we should probably have pages for all these types, so maybe we should just create links to all of them and write pages for those that don't exist]. Also link styling is at odds with syntax highlighting, and I'm not sure how best to resolve that.

Things this version does do that the old one didn't

  • pretty-printing: it does really simple pretty-printing: basically if any type's combinator is anything other than " " (juxtaposition) then it renders the type in separate lines, aligning them, at the top-level only. So rather than:

     this | that | the other
    

    you get:

    this      |
    that      |
    the other |
    

    There's definitely room to think about what would be ideal here, but I think this greatly reduces the wall of text feel of the formal syntax.

  • syntax highlighting: again, really basic, just highlighting properties, types, keywords, and functions. I’ve used the same classes that we already use for CSS syntax highlighting, so we get the same colours.

Some before and after

animation

Screen Shot 2021-09-10 at 17 18 27

Screen Shot 2021-09-10 at 17 18 53

grid-template

Screen Shot 2021-09-10 at 17 19 15

Screen Shot 2021-09-10 at 20 48 10

One obvious regression is that the formal syntax is much longer now. If we wanted to we could easily show only the top-level type and hide the rest in a <details> element. Or we could decide that pretty-printing isn't worth the extra space (but I think it is).

@idoros
Copy link
Contributor

idoros commented Sep 12, 2021

This is definitely the way this should go in my opinion. Great improvement over the current regex parsing. and I really like the pretty printing, makes everything much more readable.

Just a few notes:

this version only works with CSS properties, not selectors or at-rules. This is because webref doesn't include data for anything except properties (as far as I could see, but maybe I am wrong?)

webref seems to have syntax for at-rules and selectors. for example @media. The only thing is that the top <media-query-list> data type definition is not in that file, but it can be found in the repository, although I'm not sure how it might be imported or referenced to the @media params like it is today.

this version doesn't include tooltips and links for combinators (e.g. "||, "|" etc), only for multipliers ("*", "?" etc). That's because css-tree doesn't give me easy access to those things. We could do some regex hackery to fix that, if it seems important.

These links helped me quite a lot over the years, and I think it would be a shame to lose them.

this version currently doesn't include links from types

I think that like you said, internal links are less important, but the external ones are very helpful, current version seems to build links to /docs/Web/CSS/${property} and in most cases the links works, we can probably run a script to collect all generated links and filter out missing pages (maybe even add a test that makes sure the MDN link exist at build).

link styling is at odds with syntax highlighting, and I'm not sure how best to resolve that.

In my opinion links are more important than syntax coloring, maybe there is some combination that would keep the link accessible while still styling it in a way to emphasis the syntax.

@wbamberg
Copy link
Collaborator Author

wbamberg commented Sep 12, 2021

Thanks for your kind and helpful comments!

this version only works with CSS properties, not selectors or at-rules. This is because webref doesn't include data for anything except properties (as far as I could see, but maybe I am wrong?)

webref seems to have syntax for at-rules and selectors. for example @media. The only thing is that the top <media-query-list> data type definition is not in that file, but it can be found in the repository, although I'm not sure how it might be imported or referenced to the @media params like it is today.

I will look into this some more.

this version doesn't include tooltips and links for combinators (e.g. "||, "|" etc), only for multipliers ("*", "?" etc). That's because css-tree doesn't give me easy access to those things. We could do some regex hackery to fix that, if it seems important.

These links helped me quite a lot over the years, and I think it would be a shame to lose them.

You're right of course, I'm just being lazy.

this version currently doesn't include links from types

I think that like you said, internal links are less important, but the external ones are very helpful, current version seems to build links to /docs/Web/CSS/${property} and in most cases the links works, we can probably run a script to collect all generated links and filter out missing pages (maybe even add a test that makes sure the MDN link exist at build).

I think it's best to keep it simple and always link, then if the target is missing file a bug to write the page! Anyway we could see how many broken links we will get, and how much work it would be to write them all.

link styling is at odds with syntax highlighting, and I'm not sure how best to resolve that.

In my opinion links are more important than syntax coloring, maybe there is some combination that would keep the link accessible while still styling it in a way to emphasis the syntax.

I just pushed an update that adds links, and they of course get underlined, so maybe it's not so bad.

@wbamberg
Copy link
Collaborator Author

this version doesn't include tooltips and links for combinators (e.g. "||, "|" etc), only for multipliers ("*", "?" etc). That's because css-tree doesn't give me easy access to those things. We could do some regex hackery to fix that, if it seems important.

These links helped me quite a lot over the years, and I think it would be a shame to lose them.

You're right of course, I'm just being lazy.

Just pushed an update that adds this back.

@wbamberg
Copy link
Collaborator Author

webref seems to have syntax for at-rules and selectors. for example @media. The only thing is that the top <media-query-list> data type definition is not in that file, but it can be found in the repository, although I'm not sure how it might be imported or referenced to the @media params like it is today.

It looks like we can map at-rule descriptors, like, say, aspect-ratio, to syntax values using the descriptors property, but although we have the underlying syntax for at rules (e.g. <media-query>) I don't understand how to map to them from an at-rule page like @media (i.e. there's no at-rules property, as there is in mdn/data). And as you say, although <media-query> is there, <media-query-list> isn't.

Similarly for selectors: although there is underlying syntax for things like <selector-list> I don't understand how to map to that syntax from a specific pseudo-class like :host(), say.

@dontcallmedom , do you know how we can do this using webref?

@idoros
Copy link
Contributor

idoros commented Sep 26, 2021

Another issue with this change is that you are flattening the properties and the value-spaces into a single record, overriding duplicates between specs. The current version in mdn takes the mdn/data that is being curated by hand. There should probably be some configuration to decide which spec to take from in order to control the syntax selection.


a few examples of differences:

<'border-bottom-color'> is currently <'border-top-color'>

and in webref:

  • spec: css-backgrounds-4: <color>#
  • spec: css-backgrounds: <color>
  • spec: CSS: <color> | transparent | inherit <- this would be used

<'align-self'> is currently auto | normal | stretch | <baseline-position> | <overflow-position>? <self-position>

and in webref:

  • spec: css-align: auto | normal | stretch | <baseline-position> | <overflow-position>? <self-position>
  • spec: css-flexbox: auto | flex-start | flex-end | center | baseline | stretch <- this would be used

<'text-align'> is currently start | end | left | right | center | justify | match-parent

and in webref:

  • spec: css-text: start | end | left | right | center | justify | match-parent | justify-all
  • spec: CSS: left | right | center | justify | inherit <- this would be used

<'margin-top'> is currently <length> | <percentage> | auto

and in webref:

  • spec: css-box: <length-percentage> | auto
  • spec: CSS: <margin-width> | inherit <- this would be used (notice that margin-width is not defined anywhere)

There are a few issues:

  • version selection: control over which version of the syntax mdn should display (maybe provide a user option to see diffs between specs)
  • potentially non unique value-space syntax. I'm not sure the specs guarantee unique names in non property syntax (although it would be great if they did that).
  • some property syntax is published with CSS-wide keywords, specifically all the properties in the CSS spec are written with inherit.
List of duplicate/updated syntax between specs (ordered in according to `webref/css` listAll )
  • <single-animation>
    • spec: css-animations-2:
    • <time> || <easing-function> || <time> || <single-animation-iteration-count> || <single-animation-direction> || <single-animation-fill-mode> || <single-animation-play-state> || [ none | <keyframes-name> ] || <single-animation-timeline>
    • spec: css-animations:
    • <time> || <easing-function> || <time> || <single-animation-iteration-count> || <single-animation-direction> || <single-animation-fill-mode> || <single-animation-play-state> || [ none | <keyframes-name> ]
  • <'background-position'>
    • spec: css-backgrounds-4:
    • <position>#
    • spec: css-backgrounds:
    • <bg-position>#
    • spec: CSS:
    • [ [ <percentage> | <length> | left | center | right ] [ <percentage> | <length> | top | center | bottom ]? ] | [ [ left | center | right ] || [ top | center | bottom ] ] | inherit
  • <'background-clip'>
    • spec: css-backgrounds-4:
    • <bg-clip>#
    • spec: css-backgrounds:
    • <box>#
  • <'border-top-color'>
    • spec: css-backgrounds-4:
    • <color>#
    • spec: css-backgrounds:
    • <color>
    • spec: CSS:
    • <color> | transparent | inherit
  • <'border-right-color'>
    • spec: css-backgrounds-4:
    • <color>#
    • spec: css-backgrounds:
    • <color>
    • spec: CSS:
    • <color> | transparent | inherit
  • <'border-bottom-color'>
    • spec: css-backgrounds-4:
    • <color>#
    • spec: css-backgrounds:
    • <color>
    • spec: CSS:
    • <color> | transparent | inherit
  • <'border-left-color'>
    • spec: css-backgrounds-4:
    • <color>#
    • spec: css-backgrounds:
    • <color>
    • spec: CSS:
    • <color> | transparent | inherit
  • <'border-color'>
    • spec: css-backgrounds-4:
    • <color>#{1,4}
    • spec: css-backgrounds:
    • <color>{1,4}
    • spec: CSS:
    • [ <color> | transparent ]{1,4} | inherit
  • <'border-radius'>
    • spec: css-backgrounds-4:
    • <length-percentage [0,∞]>{1,4} [ / <length-percentage [0,∞]>{1,4} ]?
    • spec: css-backgrounds:
    • <length-percentage [0,∞]>{1,4} [ / <length-percentage [0,∞]>{1,4} ]?
  • <rgb()>
    • spec: css-color-5:
    • rgb( <percentage>{3} [ / <alpha-value> ]? ) | rgb( <number>{3} [ / <alpha-value> ]? ) | rgb( [ from <color> ]? [ <number> | <percentage> ]{3} [ / <alpha-value> ]? )
    • spec: css-color:
    • rgb( <percentage>{3} [ / <alpha-value> ]? ) | rgb( <number>{3} [ / <alpha-value> ]? )
  • <hsl()>
    • spec: css-color-5:
    • hsl([from <color>]? <hue> <percentage> <percentage> [ / <alpha-value> ]? )
    • spec: css-color:
    • hsl( <hue> <percentage> <percentage> [ / <alpha-value> ]? )
  • <hwb()>
    • spec: css-color-5:
    • hwb([from <color>]? <hue> <percentage> <percentage> [ / <alpha-value> ]? )
    • spec: css-color:
    • hwb( <hue> <percentage> <percentage> [ / <alpha-value> ]? )
  • <lab()>
    • spec: css-color-5:
    • lab([from <color>]? <percentage> <number> <number> [ / <alpha-value> ]? )
    • spec: css-color:
    • lab( <percentage> <number> <number> [ / <alpha-value> ]? )
  • <lch()>
    • spec: css-color-5:
    • lch([from <color>]? <percentage> <number> <hue> [ / <alpha-value> ]? )
    • spec: css-color:
    • lch( <percentage> <number> <hue> [ / <alpha-value> ]? )
  • <color()>
    • spec: css-color-5:
    • color( [from <color>]? <colorspace-params> [ / <alpha-value> ]? )
    • spec: css-color:
    • color( [<ident> | <dashed-ident>] [ <number-percentage>+ ] [ / <alpha-value> ]? )
  • <supports-feature>
    • spec: css-conditional-4:
    • <supports-selector-fn> | <supports-font-technology-fn> | <supports-decl>
    • spec: css-conditional:
    • <supports-decl>
  • <'justify-content'>
    • spec: css-align:
    • normal | <content-distribution> | <overflow-position>? [ <content-position> | left | right ]
    • spec: css-flexbox:
    • flex-start | flex-end | center | space-between | space-around
  • <'align-items'>
    • spec: css-align:
    • normal | stretch | <baseline-position> | [ <overflow-position>? <self-position> ]
    • spec: css-flexbox:
    • flex-start | flex-end | center | baseline | stretch
  • <'align-self'>
    • spec: css-align:
    • auto | normal | stretch | <baseline-position> | <overflow-position>? <self-position>
    • spec: css-flexbox:
    • auto | flex-start | flex-end | center | baseline | stretch
  • <'align-content'>
    • spec: css-align:
    • normal | <baseline-position> | <content-distribution> | <overflow-position>? <content-position>
    • spec: css-flexbox:
    • flex-start | flex-end | center | space-between | space-around | stretch
  • <font-technology>
    • spec: css-conditional-4:
    • [ features-opentype | features-aat | features-graphite | color-colrv0 | color-colrv1 | color-svg | color-sbix | color-cbdt | variations | palettes | incremental ]
    • spec: css-fonts-5:
    • [features(<font-feature-technology>) | variations | color(<color-font-technology>) | palettes | incremental ]
    • spec: css-fonts:
    • [features(<font-feature-technology>) | variations | color(<color-font-technology>) | palettes | incremental ]
  • <'font-size-adjust'>
    • spec: css-fonts-5:
    • none | [ ex-height | cap-height | ch-width | ic-width | ic-height ]? [ from-font | <number> ]
    • spec: css-fonts:
    • none | <number>
  • <font-format>
    • spec: css-fonts-5:
    • [<string> | woff | truetype | opentype | woff2 | embedded-opentype | collection | svg]
    • spec: css-fonts:
    • [<string> | woff | truetype | opentype | woff2 | embedded-opentype | collection | svg]
  • <font-feature-technology>
    • spec: css-fonts-5:
    • [opentype | aat | graphite]
    • spec: css-fonts:
    • [opentype | aat | graphite]
  • <color-font-technology>
    • spec: css-fonts-5:
    • [COLRv0 | COLRv1 | SVG | sbix | CBDT ]
    • spec: css-fonts:
    • [COLRv0 | COLRv1 | SVG | sbix | CBDT ]
  • <'string-set'>
    • spec: css-content:
    • none | [ <custom-ident> <string>+ ]#
    • spec: css-gcpm:
    • [ <custom-ident> <content-list> ]# | none
  • <content()>
    • spec: css-content:
    • content( [ text | before | after | first-letter | marker ]? )
    • spec: css-gcpm:
    • content([text | before | after | first-letter ])
  • <string()>
    • spec: css-content:
    • string( <custom-ident> , [ first | start | last | first-except ]? )
    • spec: css-gcpm:
    • string( <custom-ident> , [ first | start | last | first-except ]? )
  • <element()>
    • spec: css-gcpm:
    • element( <custom-ident> , [ first | start | last | first-except ]? )
    • spec: css-images-4:
    • element( <id-selector> )
  • <'object-fit'>
    • spec: css-images-4:
    • fill | none | [contain | cover] || scale-down
    • spec: css-images:
    • fill | contain | cover | none | scale-down
  • <image>
    • spec: css-images-4:
    • <url> | <image()> | <image-set()> | <cross-fade()> | <element()> | <gradient>
    • spec: css-images:
    • <url> | <gradient>
  • <gradient>
    • spec: css-images-4:
    • [ <linear-gradient()> | <repeating-linear-gradient()> | <radial-gradient()> | <repeating-radial-gradient()> | <conic-gradient()> | <repeating-conic-gradient()> ]
    • spec: css-images:
    • <linear-gradient()> | <repeating-linear-gradient()> | <radial-gradient()> | <repeating-radial-gradient()>
  • <color-stop-list>
    • spec: css-images-4:
    • <linear-color-stop> , [ <linear-color-hint>? , <linear-color-stop> ]#
    • spec: css-images:
    • <linear-color-stop> , [ <linear-color-hint>? , <linear-color-stop> ]#
  • <linear-color-stop>
    • spec: css-images-4:
    • <color> && <color-stop-length>?
    • spec: css-images:
    • <color> && <length-percentage>?
  • <linear-color-hint>
    • spec: css-images-4:
    • <length-percentage>
    • spec: css-images:
    • <length-percentage>
  • <'column-span'>
    • spec: css-multicol-2:
    • none | <integer [1,∞]> | all | auto
    • spec: css-multicol:
    • none | all
  • <'text-overflow'>
    • spec: css-overflow-4:
    • [ clip | ellipsis | <string> | fade | <fade()> ]{1,2}
    • spec: css-overflow:
    • clip | ellipsis
  • <'max-lines'>
    • spec: css-overflow-4:
    • none | <integer>
    • spec: css-overflow:
    • none | <integer>
  • <'continue'>
    • spec: css-overflow-4:
    • auto | overflow | paginate | fragments | discard
    • spec: css-overflow:
    • auto | discard
  • <'inset-block-start'>
    • spec: css-logical:
    • <'top'>
    • spec: css-position:
    • auto | <length-percentage>
  • <'inset-inline-start'>
    • spec: css-logical:
    • <'top'>
    • spec: css-position:
    • auto | <length-percentage>
  • <'inset-block-end'>
    • spec: css-logical:
    • <'top'>
    • spec: css-position:
    • auto | <length-percentage>
  • <'inset-inline-end'>
    • spec: css-logical:
    • <'top'>
    • spec: css-position:
    • auto | <length-percentage>
  • <'inset-block'>
    • spec: css-logical:
    • <'top'>{1,2}
    • spec: css-position:
    • <top>{1,2}
  • <'inset-inline'>
    • spec: css-logical:
    • <'top'>{1,2}
    • spec: css-position:
    • <top>{1,2}
  • <'inset'>
    • spec: css-logical:
    • <'top'>{1,4}
    • spec: css-position:
    • <top>{1,4}
  • <'shape-inside'>
    • spec: css-round-display:
    • auto | outside-shape | [ <basic-shape> || shape-box ] | <image> | display
    • spec: css-shapes-2:
    • auto | outside-shape | [ <basic-shape> || shape-box ] | <image> | display
    • spec: SVG:
    • auto | [ <basic-shape> | <uri> ]+
  • <fit-content()>
    • spec: css-grid:
    • fit-content( <length-percentage> )
    • spec: css-sizing:
    • fit-content(<length-percentage>)
  • <'text-decoration-line'>
    • spec: css-text-decor-4:
    • none | [ underline || overline || line-through || blink ] | spelling-error | grammar-error
    • spec: css-text-decor:
    • none | [ underline || overline || line-through || blink ]
  • <'text-decoration-style'>
    • spec: css-text-decor-4:
    • solid | double | dotted | dashed | wavy
    • spec: css-text-decor:
    • solid | double | dotted | dashed | wavy
  • <'text-decoration-color'>
    • spec: css-text-decor-4:
    • <color>
    • spec: css-text-decor:
    • <color>
  • <'text-decoration'>
    • spec: css-text-decor-4:
    • <'text-decoration-line'> || <'text-decoration-thickness'> || <'text-decoration-style'> || <'text-decoration-color'>
    • spec: css-text-decor:
    • <'text-decoration-line'> || <'text-decoration-style'> || <'text-decoration-color'>
    • spec: CSS:
    • none | [ underline || overline || line-through || blink ] | inherit
  • <'text-underline-position'>
    • spec: css-text-decor-4:
    • auto | [ from-font | under ] || [ left | right ]
    • spec: css-text-decor:
    • auto | [ under || [ left | right ] ]
  • <'text-emphasis-style'>
    • spec: css-text-decor-4:
    • none | [ [ filled | open ] || [ dot | circle | double-circle | triangle | sesame ] ] | <string>
    • spec: css-text-decor:
    • none | [ [ filled | open ] || [ dot | circle | double-circle | triangle | sesame ] ] | <string>
  • <'text-emphasis-color'>
    • spec: css-text-decor-4:
    • <color>
    • spec: css-text-decor:
    • <color>
  • <'text-emphasis'>
    • spec: css-text-decor-4:
    • <'text-emphasis-style'> || <'text-emphasis-color'>
    • spec: css-text-decor:
    • <'text-emphasis-style'> || <'text-emphasis-color'>
  • <'text-emphasis-position'>
    • spec: css-text-decor-4:
    • [ over | under ] && [ right | left ]?
    • spec: css-text-decor:
    • [ over | under ] && [ right | left ]?
  • <'text-shadow'>
    • spec: css-text-decor-4:
    • none | [ <color>? && <length>{2,4} ]#
    • spec: css-text-decor:
    • none | [ <color>? && <length>{2,3} ]#
  • <'white-space'>
    • spec: css-text-4:
    • normal | pre | nowrap | pre-wrap | pre-line
    • spec: css-text:
    • normal | pre | nowrap | pre-wrap | break-spaces | pre-line
    • spec: CSS:
    • normal | pre | nowrap | pre-wrap | pre-line | inherit
  • <scale()>
    • spec: css-transforms-2:
    • scale( [ <number> | <percentage> ]#{1,2} )
    • spec: css-transforms:
    • scale( <number> , <number>? )
  • <scaleX()>
    • spec: css-transforms-2:
    • scaleX( [ <number> | <percentage> ] )
    • spec: css-transforms:
    • scaleX( <number> )
  • <scaleY()>
    • spec: css-transforms-2:
    • scaleY( [ <number> | <percentage> ] )
    • spec: css-transforms:
    • scaleY( <number> )
  • <position>
    • spec: css-backgrounds-4:
    • [ [ left | center | right | top | bottom | start | end | <length-percentage> ] | [ left | center | right | x-start | x-end | <length-percentage> ] [ top | center | bottom | y-start | y-end | <length-percentage> ] | [ center | [ left | right | x-start | x-end ] <length-percentage>? ] && [ center | [ top | bottom | y-start | y-end ] <length-percentage>? ] | [ center | [ start | end ] <length-percentage>? ] [ center | [ start | end ] <length-percentage>? ] ]
    • spec: css-values:
    • [ [ left | center | right ] || [ top | center | bottom ] | [ left | center | right | <length-percentage> ] [ top | center | bottom | <length-percentage> ]? | [ [ left | right ] <length-percentage> ] && [ [ top | bottom ] <length-percentage> ] ]
  • <'margin-top'>
    • spec: css-box:
    • <length-percentage> | auto
    • spec: CSS:
    • <margin-width> | inherit
  • <'margin-bottom'>
    • spec: css-box:
    • <length-percentage> | auto
    • spec: CSS:
    • <margin-width> | inherit
  • <'margin-right'>
    • spec: css-box:
    • <length-percentage> | auto
    • spec: CSS:
    • <margin-width> | inherit
  • <'margin-left'>
    • spec: css-box:
    • <length-percentage> | auto
    • spec: CSS:
    • <margin-width> | inherit
  • <'margin'>
    • spec: css-box:
    • <'margin-top'>{1,4}
    • spec: CSS:
    • <margin-width>{1,4} | inherit
  • <'padding-top'>
    • spec: css-box:
    • <length-percentage>
    • spec: CSS:
    • <padding-width> | inherit
  • <'padding-right'>
    • spec: css-box:
    • <length-percentage>
    • spec: CSS:
    • <padding-width> | inherit
  • <'padding-bottom'>
    • spec: css-box:
    • <length-percentage>
    • spec: CSS:
    • <padding-width> | inherit
  • <'padding-left'>
    • spec: css-box:
    • <length-percentage>
    • spec: CSS:
    • <padding-width> | inherit
  • <'padding'>
    • spec: css-box:
    • <'padding-top'>{1,4}
    • spec: CSS:
    • <padding-width>{1,4} | inherit
  • <'border-top-width'>
    • spec: css-backgrounds:
    • <line-width>
    • spec: CSS:
    • <border-width> | inherit
  • <'border-right-width'>
    • spec: css-backgrounds:
    • <line-width>
    • spec: CSS:
    • <border-width> | inherit
  • <'border-bottom-width'>
    • spec: css-backgrounds:
    • <line-width>
    • spec: CSS:
    • <border-width> | inherit
  • <'border-left-width'>
    • spec: css-backgrounds:
    • <line-width>
    • spec: CSS:
    • <border-width> | inherit
  • <'border-width'>
    • spec: css-backgrounds:
    • <line-width>{1,4}
    • spec: CSS:
    • <border-width>{1,4} | inherit
  • <'border-top-style'>
    • spec: css-backgrounds:
    • <line-style>
    • spec: CSS:
    • <border-style> | inherit
  • <'border-right-style'>
    • spec: css-backgrounds:
    • <line-style>
    • spec: CSS:
    • <border-style> | inherit
  • <'border-bottom-style'>
    • spec: css-backgrounds:
    • <line-style>
    • spec: CSS:
    • <border-style> | inherit
  • <'border-left-style'>
    • spec: css-backgrounds:
    • <line-style>
    • spec: CSS:
    • <border-style> | inherit
  • <'border-style'>
    • spec: css-backgrounds:
    • <line-style>{1,4}
    • spec: CSS:
    • <border-style>{1,4} | inherit
  • <'border-top'>
    • spec: css-backgrounds:
    • <line-width> || <line-style> || <color>
    • spec: CSS:
    • [ <border-width> || <border-style> || <'border-top-color'> ] | inherit
  • <'border-right'>
    • spec: css-backgrounds:
    • <line-width> || <line-style> || <color>
    • spec: CSS:
    • [ <border-width> || <border-style> || <'border-top-color'> ] | inherit
  • <'border-bottom'>
    • spec: css-backgrounds:
    • <line-width> || <line-style> || <color>
    • spec: CSS:
    • [ <border-width> || <border-style> || <'border-top-color'> ] | inherit
  • <'border-left'>
    • spec: css-backgrounds:
    • <line-width> || <line-style> || <color>
    • spec: CSS:
    • [ <border-width> || <border-style> || <'border-top-color'> ] | inherit
  • <'border'>
    • spec: css-backgrounds:
    • <line-width> || <line-style> || <color>
    • spec: CSS:
    • [ <border-width> || <border-style> || <'border-top-color'> ] | inherit
  • <'display'>
    • spec: css-display:
    • [ <display-outside> || <display-inside> ] | <display-listitem> | <display-internal> | <display-box> | <display-legacy>
    • spec: CSS:
    • inline | block | list-item | inline-block | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | none | inherit
  • <'position'>
    • spec: css-position:
    • static | relative | absolute | sticky | fixed
    • spec: CSS:
    • static | relative | absolute | fixed | inherit
  • <'top'>
    • spec: css-position:
    • auto | <length-percentage>
    • spec: CSS:
    • <length> | <percentage> | auto | inherit
  • <'right'>
    • spec: css-position:
    • auto | <length-percentage>
    • spec: CSS:
    • <length> | <percentage> | auto | inherit
  • <'bottom'>
    • spec: css-position:
    • auto | <length-percentage>
    • spec: CSS:
    • <length> | <percentage> | auto | inherit
  • <'left'>
    • spec: css-position:
    • auto | <length-percentage>
    • spec: CSS:
    • <length> | <percentage> | auto | inherit
  • <'float'>
    • spec: css-page-floats:
    • block-start | block-end | inline-start | inline-end | snap-block | <snap-block()> | snap-inline | <snap-inline()> | left | right | top | bottom | none
    • spec: CSS:
    • left | right | none | inherit
  • <'clear'>
    • spec: css-page-floats:
    • inline-start | inline-end | block-start | block-end | left | right | top | bottom | none
    • spec: CSS:
    • none | left | right | both | inherit
  • <'direction'>
    • spec: css-writing-modes:
    • ltr | rtl
    • spec: CSS:
    • ltr | rtl | inherit
  • <'unicode-bidi'>
    • spec: css-writing-modes:
    • normal | embed | isolate | bidi-override | isolate-override | plaintext
    • spec: CSS:
    • normal | embed | bidi-override | inherit
  • <'width'>
    • spec: css-sizing:
    • auto | <length-percentage> | min-content | max-content | fit-content(<length-percentage>)
    • spec: CSS:
    • <length> | <percentage> | auto | inherit
  • <'min-width'>
    • spec: css-sizing:
    • auto | <length-percentage> | min-content | max-content | fit-content(<length-percentage>)
    • spec: CSS:
    • <length> | <percentage> | inherit
  • <'max-width'>
    • spec: css-sizing:
    • none | <length-percentage> | min-content | max-content | fit-content(<length-percentage>)
    • spec: CSS:
    • <length> | <percentage> | none | inherit
  • <'height'>
    • spec: css-sizing:
    • auto | <length-percentage> | min-content | max-content | fit-content(<length-percentage>)
    • spec: CSS:
    • <length> | <percentage> | auto | inherit
  • <'min-height'>
    • spec: css-sizing:
    • auto | <length-percentage> | min-content | max-content | fit-content(<length-percentage>)
    • spec: CSS:
    • <length> | <percentage> | inherit
  • <'max-height'>
    • spec: css-sizing:
    • none | <length-percentage> | min-content | max-content | fit-content(<length-percentage>)
    • spec: CSS:
    • <length> | <percentage> | none | inherit
  • <'line-height'>
    • spec: css-inline:
    • normal | <number> | <length-percentage>
    • spec: CSS:
    • normal | <number> | <length> | <percentage> | inherit
  • <'vertical-align'>
    • spec: css-inline:
    • [ first | last] || <'alignment-baseline'> || <'baseline-shift'>
    • spec: CSS:
    • baseline | sub | super | top | text-top | middle | bottom | text-bottom | <percentage> | <length> | inherit
  • <'overflow'>
    • spec: css-overflow:
    • [ visible | hidden | clip | scroll | auto ]{1,2}
    • spec: CSS:
    • visible | hidden | scroll | auto | inherit
  • <'clip'>
    • spec: css-masking:
    • rect() | auto
    • spec: CSS:
    • <shape> | auto | inherit
  • <'visibility'>
    • spec: css-display:
    • visible | hidden | collapse
    • spec: CSS:
    • visible | hidden | collapse | inherit
  • <'content'>
    • spec: css-content:
    • normal | none | [ <content-replacement> | <content-list> ] [/ [ <string> | <counter> ]+ ]?
    • spec: CSS:
    • normal | none | [ <string> | <uri> | <counter> | attr(<identifier>) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | inherit
  • <'quotes'>
    • spec: css-content:
    • auto | none | [ <string> <string> ]+
    • spec: CSS:
    • [<string> <string>]+ | none | inherit
  • <'counter-reset'>
    • spec: css-lists:
    • [ <counter-name> <integer>? | <reversed-counter-name> <integer>? ]+ | none
    • spec: CSS:
    • [ <identifier> <integer>? ]+ | none | inherit
  • <'counter-increment'>
    • spec: css-lists:
    • [ <counter-name> <integer>? ]+ | none
    • spec: CSS:
    • [ <identifier> <integer>? ]+ | none | inherit
  • <'list-style-type'>
    • spec: css-lists:
    • <counter-style> | <string> | none
    • spec: CSS:
    • disc | circle | square | decimal | decimal-leading-zero | lower-roman | upper-roman | lower-greek | lower-latin | upper-latin | armenian | georgian | lower-alpha | upper-alpha | none | inherit
  • <'list-style-image'>
    • spec: css-lists:
    • <image> | none
    • spec: CSS:
    • <uri> | none | inherit
  • <'list-style-position'>
    • spec: css-lists:
    • inside | outside
    • spec: CSS:
    • inside | outside | inherit
  • <'list-style'>
    • spec: css-lists:
    • <'list-style-position'> || <'list-style-image'> || <'list-style-type'>
    • spec: CSS:
    • [ <'list-style-type'> || <'list-style-position'> || <'list-style-image'> ] | inherit
  • <'orphans'>
    • spec: css-break:
    • <integer>
    • spec: CSS:
    • <integer> | inherit
  • <'widows'>
    • spec: css-break:
    • <integer>
    • spec: CSS:
    • <integer> | inherit
  • <'color'>
    • spec: css-color:
    • <color>
    • spec: CSS:
    • <color> | inherit
  • <'background-color'>
    • spec: css-backgrounds:
    • <color>
    • spec: CSS:
    • <color> | transparent | inherit
  • <'background-image'>
    • spec: css-backgrounds:
    • <bg-image>#
    • spec: CSS:
    • <uri> | none | inherit
  • <'background-repeat'>
    • spec: css-backgrounds:
    • <repeat-style>#
    • spec: CSS:
    • repeat | repeat-x | repeat-y | no-repeat | inherit
  • <'background-attachment'>
    • spec: css-backgrounds:
    • <attachment>#
    • spec: CSS:
    • scroll | fixed | inherit
  • <'background'>
    • spec: css-backgrounds:
    • [<bg-layer># ,]? <final-bg-layer>
    • spec: CSS:
    • [<'background-color'> || <'background-image'> || <'background-repeat'> || <'background-attachment'> || <'background-position'>] | inherit
  • <'font-family'>
    • spec: css-fonts:
    • [ <family-name> | <generic-family> ]#
    • spec: CSS:
    • [[ <family-name> | <generic-family> ] [, <family-name> | <generic-family>]* ] | inherit
  • <'font-style'>
    • spec: css-fonts:
    • normal | italic | oblique <angle>?
    • spec: CSS:
    • normal | italic | oblique | inherit
  • <'font-variant'>
    • spec: css-fonts:
    • normal | none | [ <common-lig-values> || <discretionary-lig-values> || <historical-lig-values> || <contextual-alt-values> || [ small-caps | all-small-caps | petite-caps | all-petite-caps | unicase | titling-caps ] || [ stylistic(<feature-value-name>) || historical-forms || styleset(<feature-value-name>#) || character-variant(<feature-value-name>#) || swash(<feature-value-name>) || ornaments(<feature-value-name>) || annotation(<feature-value-name>) ] || <numeric-figure-values> || <numeric-spacing-values> || <numeric-fraction-values> || ordinal || slashed-zero || <east-asian-variant-values> || <east-asian-width-values> || ruby || [ sub | super ] ]
    • spec: CSS:
    • normal | small-caps | inherit
  • <'font-weight'>
    • spec: css-fonts:
    • <font-weight-absolute> | bolder | lighter
    • spec: CSS:
    • normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | inherit
  • <'font-size'>
    • spec: css-fonts:
    • <absolute-size> | <relative-size> | <length-percentage>
    • spec: CSS:
    • <absolute-size> | <relative-size> | <length> | <percentage> | inherit
  • <'font'>
    • spec: css-fonts:
    • [ [ <'font-style'> || <font-variant-css2> || <'font-weight'> || <font-stretch-css3> ]? <'font-size'> [ / <'line-height'> ]? <'font-family'> ] | caption | icon | menu | message-box | small-caption | status-bar
    • spec: CSS:
    • [ [ <'font-style'> || <'font-variant'> || <'font-weight'> ]? <'font-size'> [ / <'line-height'> ]? <'font-family'> ] | caption | icon | menu | message-box | small-caption | status-bar | inherit
  • <'text-indent'>
    • spec: css-text:
    • [ <length-percentage> ] && hanging? && each-line?
    • spec: CSS:
    • <length> | <percentage> | inherit
  • <'text-align'>
    • spec: css-text:
    • start | end | left | right | center | justify | match-parent | justify-all
    • spec: CSS:
    • left | right | center | justify | inherit
  • <'letter-spacing'>
    • spec: css-text:
    • normal | <length>
    • spec: CSS:
    • normal | <length> | inherit
  • <'word-spacing'>
    • spec: css-text:
    • normal | <length>
    • spec: CSS:
    • normal | <length> | inherit
  • <'text-transform'>
    • spec: css-text:
    • none | [capitalize | uppercase | lowercase ] || full-width || full-size-kana
    • spec: CSS:
    • capitalize | uppercase | lowercase | none | inherit
  • <'caption-side'>
    • spec: css-tables:
    • top | bottom
    • spec: CSS:
    • top | bottom | inherit
  • <'table-layout'>
    • spec: css-tables:
    • auto | fixed
    • spec: CSS:
    • auto | fixed | inherit
  • <'border-collapse'>
    • spec: css-tables:
    • separate | collapse
    • spec: CSS:
    • collapse | separate | inherit
  • <'border-spacing'>
    • spec: css-tables:
    • <length>{1,2}
    • spec: CSS:
    • <length> <length>? | inherit
  • <'empty-cells'>
    • spec: css-tables:
    • show | hide
    • spec: CSS:
    • show | hide | inherit
  • <'cursor'>
    • spec: css-ui:
    • [ [<url> [<x> <y>]?,]* [ auto | default | none | context-menu | help | pointer | progress | wait | cell | crosshair | text | vertical-text | alias | copy | move | no-drop | not-allowed | grab | grabbing | e-resize | n-resize | ne-resize | nw-resize | s-resize | se-resize | sw-resize | w-resize | ew-resize | ns-resize | nesw-resize | nwse-resize | col-resize | row-resize | all-scroll | zoom-in | zoom-out ] ]
    • spec: CSS:
    • [ [<uri> ,]* [ auto | crosshair | default | pointer | move | e-resize | ne-resize | nw-resize | n-resize | se-resize | sw-resize | s-resize | w-resize | text | wait | help | progress ] ] | inherit
  • <'outline'>
    • spec: css-ui:
    • [ <'outline-color'> || <'outline-style'> || <'outline-width'> ]
    • spec: CSS:
    • [ <'outline-color'> || <'outline-style'> || <'outline-width'> ] | inherit
  • <'outline-width'>
    • spec: css-ui:
    • <line-width>
    • spec: CSS:
    • <border-width> | inherit
  • <'outline-style'>
    • spec: css-ui:
    • auto | <outline-line-style>
    • spec: CSS:
    • <border-style> | inherit
  • <'outline-color'>
    • spec: css-ui:
    • <color> | invert
    • spec: CSS:
    • <color> | invert | inherit
  • <attr()>
    • spec: css-values:
    • attr( <wq-name> <attr-type>? , <declaration-value>?)
    • spec: CSS:
    • attr(X)
  • <media-query>
    • spec: mediaqueries-5:
    • <media-condition> | [ not | only ]? <media-type> [ and <media-condition-without-or> ]?
    • spec: mediaqueries:
    • <media-condition> | [ not | only ]? <media-type> [ and <media-condition-without-or> ]?
  • <media-type>
    • spec: mediaqueries-5:
    • <ident>
    • spec: mediaqueries:
    • <ident>
  • <media-condition>
    • spec: mediaqueries-5:
    • <media-not> | <media-in-parens> [ <media-and>* | <media-or>* ]
    • spec: mediaqueries:
    • <media-not> | <media-in-parens> [ <media-and>* | <media-or>* ]
  • <media-condition-without-or>
    • spec: mediaqueries-5:
    • <media-not> | <media-in-parens> <media-and>*
    • spec: mediaqueries:
    • <media-not> | <media-in-parens> <media-and>*
  • <media-not>
    • spec: mediaqueries-5:
    • not <media-in-parens>
    • spec: mediaqueries:
    • not <media-in-parens>
  • <media-and>
    • spec: mediaqueries-5:
    • and <media-in-parens>
    • spec: mediaqueries:
    • and <media-in-parens>
  • <media-or>
    • spec: mediaqueries-5:
    • or <media-in-parens>
    • spec: mediaqueries:
    • or <media-in-parens>
  • <media-in-parens>
    • spec: mediaqueries-5:
    • ( <media-condition> ) | <media-feature> | <general-enclosed>
    • spec: mediaqueries:
    • ( <media-condition> ) | <media-feature> | <general-enclosed>
  • <media-feature>
    • spec: mediaqueries-5:
    • ( [ <mf-plain> | <mf-boolean> | <mf-range> ] )
    • spec: mediaqueries:
    • ( [ <mf-plain> | <mf-boolean> | <mf-range> ] )
  • <mf-plain>
    • spec: mediaqueries-5:
    • <mf-name> : <mf-value>
    • spec: mediaqueries:
    • <mf-name> : <mf-value>
  • <mf-boolean>
    • spec: mediaqueries-5:
    • <mf-name>
    • spec: mediaqueries:
    • <mf-name>
  • <mf-range>
    • spec: mediaqueries-5:
    • <mf-name> <mf-comparison> <mf-value> | <mf-value> <mf-comparison> <mf-name> | <mf-value> <mf-lt> <mf-name> <mf-lt> <mf-value> | <mf-value> <mf-gt> <mf-name> <mf-gt> <mf-value>
    • spec: mediaqueries:
    • <mf-name> <mf-comparison> <mf-value> | <mf-value> <mf-comparison> <mf-name> | <mf-value> <mf-lt> <mf-name> <mf-lt> <mf-value> | <mf-value> <mf-gt> <mf-name> <mf-gt> <mf-value>
  • <mf-name>
    • spec: mediaqueries-5:
    • <ident>
    • spec: mediaqueries:
    • <ident>
  • <mf-value>
    • spec: mediaqueries-5:
    • <number> | <dimension> | <ident> | <ratio>
    • spec: mediaqueries:
    • <number> | <dimension> | <ident> | <ratio>
  • <mf-lt>
    • spec: mediaqueries-5:
    • '<' '='?
    • spec: mediaqueries:
    • '<' '='?
  • <mf-gt>
    • spec: mediaqueries-5:
    • '>' '='?
    • spec: mediaqueries:
    • '>' '='?
  • <mf-eq>
    • spec: mediaqueries-5:
    • '='
    • spec: mediaqueries:
    • '='
  • <mf-comparison>
    • spec: mediaqueries-5:
    • <mf-lt> | <mf-gt> | <mf-eq>
    • spec: mediaqueries:
    • <mf-lt> | <mf-gt> | <mf-eq>
  • <general-enclosed>
    • spec: mediaqueries-5:
    • [ <function-token> <any-value> ) ] | ( <ident> <any-value> )
    • spec: mediaqueries:
    • [ <function-token> <any-value> ) ] | ( <ident> <any-value> )
  • <path()>
    • spec: css-shapes:
    • path( [<'fill-rule'>,]? <string> )
    • spec: motion:
    • path( <string> )
  • <'stroke'>
    • spec: fill-stroke:
    • <'background'> with modifications
    • spec: svg-strokes:
    • <paint>
    • spec: SVG:
    • <paint>
  • <'stroke-opacity'>
    • spec: fill-stroke:
    • <'opacity'>
    • spec: svg-strokes:
    • <number>
    • spec: SVG:
    • <'opacity'>
  • <'stroke-width'>
    • spec: fill-stroke:
    • <length-percentage>#
    • spec: svg-strokes:
    • <percentage> | <length>
    • spec: SVG:
    • <length-percentage> | <number>
  • <'stroke-linecap'>
    • spec: fill-stroke:
    • butt | round | square
    • spec: svg-strokes:
    • butt | round | square
    • spec: SVG:
    • butt | round | square
  • <'stroke-linejoin'>
    • spec: fill-stroke:
    • [ crop | arcs | miter ] || [ bevel | round | fallback ]
    • spec: svg-strokes:
    • miter | miter-clip | round | bevel | arcs
    • spec: SVG:
    • miter | miter-clip | round | bevel | arcs
  • <'stroke-miterlimit'>
    • spec: fill-stroke:
    • <number>
    • spec: svg-strokes:
    • <number>
    • spec: SVG:
    • <number>
  • <'stroke-dasharray'>
    • spec: fill-stroke:
    • none | <length-percentage>+#
    • spec: svg-strokes:
    • none | <dasharray>
    • spec: SVG:
    • none | <dasharray>
  • <'stroke-dashoffset'>
    • spec: fill-stroke:
    • <length-percentage>
    • spec: svg-strokes:
    • <length> | <percentage>
    • spec: SVG:
    • <length-percentage> | <number>
  • <'inline-size'>
    • spec: css-logical:
    • <'width'>
    • spec: SVG:
    • auto | <length-percentage>
  • <'shape-margin'>
    • spec: css-shapes:
    • <length-percentage>
    • spec: SVG:
    • <length-percentage>
  • <'fill'>
    • spec: fill-stroke:
    • <'background'> with modifications
    • spec: SVG:
    • <paint>
  • <'fill-rule'>
    • spec: fill-stroke:
    • nonzero | evenodd
    • spec: SVG:
    • nonzero | evenodd
  • <'fill-opacity'>
    • spec: fill-stroke:
    • <'opacity'>
    • spec: SVG:
    • <'opacity'>
  • <'image-rendering'>
    • spec: css-images:
    • auto | smooth | high-quality | pixelated | crisp-edges
    • spec: SVG:
    • auto | optimizeQuality | optimizeSpeed
  • <dasharray>
    • spec: svg-strokes:
    • [ <length> | <percentage> | <number> ]#*
    • spec: SVG:
    • [ [ <length-percentage> | <number> ]+ ]#

@schalkneethling schalkneethling added 🧑‍🤝‍🧑 community contributions by our wonderful community enhancement Improves an existing feature. 🚉 platform keeping the platform healthy labels Nov 24, 2021
@Rumyra
Copy link
Contributor

Rumyra commented Dec 21, 2021

Some thoughts:

this version only works with CSS properties, not selectors or at-rules. This is because webref doesn't include data for anything except properties (as far as I could see, but maybe I am wrong?) I think it's fine to limit formal syntax to properties, but we'd need to remove macro calls from unsupported pages.

Could we litmus test it - remove formal syntax macro from pages this doesn't support and see if we get any complaints. This isn't a particular kind way of trying it, but we don't want to be stuck in a world of using both webref & data

this version doesn't have any support for l10n (except for making sure links will work). I was going to add something but it turns out that the current macro only supports "de", so dropping support doesn't seem like a regression.

Yeh as far as I can tell this isn't kept up to date in data anyway so should be ok

thinking about this some more: we should probably have pages for all these types, so maybe we should just create links to all of them and write pages for those that don't exist

Probably yes - having trawled through CSS pages more over the past few weeks we could generally do a review & tidy anyway.

Also link styling is at odds with syntax highlighting, and I'm not sure how best to resolve that.

Maybe @schalkneethling could take a look

+1 pretty printing, it looks much better with the auto new lines & better colors

One obvious regression is that the formal syntax is much longer now.

I'd be interested to see how many pages this affects, eg how many are very long and how many are actually not that long

For all the other comments maybe we can push for changes to webref based on our needs?

In short this still looks like a much better solution than we have, even if a couple of things temporarily regress. I don't see anything that's a blocker 👍

@Rumyra
Copy link
Contributor

Rumyra commented Dec 21, 2021

I did a teeny bit of asking CSS devs I knew how they felt about the 'Formal Syntax' sections and most either found them confusing or hadn't taken much notice of them - the examples at the top of CSS pages were the bit they found the most useful...

The suggestion about details summary to expand them might be a good one 👍

@schalkneethling
Copy link

Also link styling is at odds with syntax highlighting, and I'm not sure how best to resolve that.

Maybe @schalkneethling could take a look

This is changing with the redesign so I reckon there is not much sense in me looking at it until that has landed.

@caugner caugner added the macros tracking issues related to kumascript macros label Mar 11, 2022
@wbamberg
Copy link
Collaborator Author

wbamberg commented Mar 15, 2022

Coming back to this...

Another issue with this change is that you are flattening the properties and the value-spaces into a single record, overriding duplicates between specs. The current version in mdn takes the mdn/data that is being curated by hand. There should probably be some configuration to decide which spec to take from in order to control the syntax selection.

a few examples of differences:

<'border-bottom-color'> is currently <'border-top-color'>

and in webref:

  • spec: css-backgrounds-4: <color>#

  • spec: css-backgrounds: <color>

  • spec: CSS: <color> | transparent | inherit <- this would be used

You're absolutely right, the macro should be cleverer here (although I think "curated" is perhaps a generous way to describe the choices made in mdn/data).

Perhaps we could do something like: we already link to a specification in the page. We could say that this represents our configured choice, and the macro could display formal syntax from that spec. So in the case above, border-bottom-color links to css-backgrounds, so we could use that version of the syntax?

I like this because there are no additional config choices to make - the config choice is the spec we list. We do sometimes list more than one spec (e.g. align-self - what do we do then? The obvious suggestion is to list multiple versions of the syntax I suppose. I'm not sure what the rationale for sometimes listing multiple versions of the spec is. In align-self we're already inconsistent, listing values that are not in the formal syntax.

@wbamberg
Copy link
Collaborator Author

I just pushed some updates to this PR.

In #4656 (comment), @idoros raised a good question: in webref, we sometimes have multiple different definitions of the same property, from different specifications. What should we do in this case?

My suggestion was that we could use spec URLs in BCD to decide which webref spec to use. Because it seems like a good idea for the formal syntax we display to match the spec we link to.

One issue here would be: what if we have multiple spec URLs in BCD? I haven't looked into this much yet, because I'd like first to figure out how often this happens and why.

But another issue is that sometimes the spec URL in BCD does not exactly match a spec URL in webref.

For example, in background-image the spec URL is https://drafts.csswg.org/css-backgrounds/#background-image, and https://drafts.csswg.org/css-backgrounds/ matches an entry in webref, and it works great.

But, for example, font-style gives the spec URL as https://drafts.csswg.org/css-fonts/#font-style-prop, and that doesn't match an entry in webref, which instead lists:

https://drafts.csswg.org/css-fonts-5/
https://drafts.csswg.org/css-fonts-4/

What should we do in this case? The macro could map the BCD spec URL onto the highest-level corresponding spec in webref, maybe? So https://drafts.csswg.org/css-fonts/ could map to https://drafts.csswg.org/css-fonts-5/. Is that a good approach?

@dontcallmedom , @Elchi3 , @Rumyra etc, I'd love to hear what you all think about this.

@wbamberg
Copy link
Collaborator Author

Another thing is that some entries in webref don't have a value key with the formal syntax, they have a newValues which I assume should be concatenated using | onto a base value from another spec. So for instance:

https://drafts.csswg.org/css-logical-1/
CSS Logical Properties and Values Level 1
{
  name: 'caption-side',
  newValues: 'inline-start | inline-end',
  computedValue: 'specified keyword',
  styleDeclaration: [ 'caption-side', 'captionSide' ]
}

In this case there are two other specs in webref that could provide a "base value" for caption-side:

https://drafts.csswg.org/css2/
CSS 2
{
  name: 'caption-side',
  value: 'top | bottom | inherit',
  initial: 'top',
  appliesTo: 'table-caption elements',
  inherited: 'yes',
  percentages: 'N/A',
  computedValue: 'as specified',
  canonicalOrder: 'per grammar',
  media: 'visual',
  styleDeclaration: [ 'caption-side', 'captionSide' ]
}

https://drafts.csswg.org/css-tables-3/
CSS Table Module Level 3
{
  name: 'caption-side',
  value: 'top | bottom',
  initial: 'top',
  appliesTo: 'table-caption boxes',
  inherited: 'yes',
  percentages: 'n/a',
  computedValue: 'specified keyword',
  canonicalOrder: 'per grammar',
  animationType: 'discrete',
  styleDeclaration: [ 'caption-side', 'captionSide' ]
}

I'm not sure how in general we should figure out which of these base values to choose.

There aren't all that many of these newValues properties though. Only the following properties are affected:

display
position
content
float
grid-template-columns
grid-template-rows
display
caption-side
float
clear
text-align
display
width
height
inline-size
block-size
min-width
min-height
min-inline-size
min-block-size
max-width
max-height
max-inline-size
max-block-size
column-width

Does this make sense, or am I confused?

@dontcallmedom
Copy link
Contributor

copying @tidoust

@dontcallmedom
Copy link
Contributor

What should we do in this case? The macro could map the BCD spec URL onto the highest-level corresponding spec in webref, maybe? So https://drafts.csswg.org/css-fonts/ could map to https://drafts.csswg.org/css-fonts-5/. Is that a good approach?

Mapping the unnumbered version of a draft to its numbered one can be obtained via the info in browser-specs - e.g. if you look up the series css-fonts in browser-specs, you'll find that its currentSpecification points to level 4.

That said, there may be a worthy discussion to be had about MDN/BCD using unnumbered versions - I'm not sure there is a good mechanism for MDN to track that this unnumbered version is now pointing to something else, and that the page/the BCD data may no longer reflect the content of the new version (although I guess it's more general problem of determining of MDN tracks the content of specs; maybe the formal syntax is actually a way to determine whether it does or not: in particular, maybe BCD could detect when it doesn't have data about new syntactic token identified from the formal syntax?).

Another thing is that some entries in webref don't have a value key with the formal syntax, they have a newValues which I assume should be concatenated using | onto a base value from another spec.

That's correct. @tidoust, I wonder if this points to having a consolidated view of CSS (the same way we have one for WebIDL)?

@github-actions github-actions bot added macros tracking issues related to kumascript macros merge conflicts 🚧 Please rebase onto or merge the latest main. and removed merge conflicts 🚧 Please rebase onto or merge the latest main. labels Jun 3, 2022
@github-actions
Copy link
Contributor

github-actions bot commented Jun 6, 2022

This pull request has merge conflicts that must be resolved before it can be merged.

@fiji-flo fiji-flo self-requested a review June 20, 2022 16:30
Copy link
Contributor

@fiji-flo fiji-flo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wbamberg Look great. Sorry for the delay. Could you rebase/merge main and then we can get it out.
Maybe add support for l10n. Just the scaffolding not necessarily copying all the string.s

const syntaxDescriptions = {
'*': {
fragment: 'asterisk',
tooltip: 'Asterisk: the entity may occur zero, one or several times'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we prepare this for l10n like:

    tooltip: mdn.localString({ 'en-US': 'Asterisk: the entity may occur zero, one or several times' }),

@schalkneethling
Copy link

@wbamberg Look great. Sorry for the delay. Could you rebase/merge main and then we can get it out. Maybe add support for l10n. Just the scaffolding not necessarily copying all the string.s

Thank you @fiji-flo 🎉

@github-actions github-actions bot removed the merge conflicts 🚧 Please rebase onto or merge the latest main. label Jun 21, 2022
@wbamberg
Copy link
Collaborator Author

wbamberg commented Jun 21, 2022

Thanks @fiji-flo ! I added the mdn.localString calls, and tested it on lots of pages.

I also fixed the merge conflicts, but please double check https://github.com/mdn/yari/pull/4656/files#diff-082377deab2cc777cf2c33c661c69bd5e108564a4acb9a377ce02b742562a2b9, since this was an original change I didn't make - Claas made it in 20281d2 and it conflicted with #6487.

Copy link
Contributor

@fiji-flo fiji-flo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove the replaceAll dependency and we're good to go! Great work.


const webRefData = require('@webref/css');
const { definitionSyntax } = require('css-tree');
const replaceAll = require('string.prototype.replaceall');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I missed this. We don't need this as we're now on node >= 16

@wbamberg
Copy link
Collaborator Author

-> 69c852a

@wbamberg
Copy link
Collaborator Author

I just realised that there is a bug here: when we are extracting syntax from webref, although we calculate values and newValues, we don't actually concatenate newValues onto values, so in cases like https://developer.mozilla.org/en-US/docs/Web/CSS/column-width we will miss the extra values defined in other specs, as discussed in #4656 (comment).

I just pushed 42fca89 which ought to take care of that.

Copy link
Contributor

@fiji-flo fiji-flo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

}
const newValues = parsedWebRef[specName].properties[propertyName].newValues;
if (newValues) {
newSyntaxes += ` | ${newValues}`;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch

@fiji-flo fiji-flo merged commit d6c9992 into mdn:main Jun 23, 2022
@Rumyra
Copy link
Contributor

Rumyra commented Jun 23, 2022

Wohoo!!! Awesome to see this go through :D

@dontcallmedom
Copy link
Contributor

it looks like we can map at-rule descriptors, like, say, aspect-ratio, to syntax values using the descriptors property, but although we have the underlying syntax for at rules (e.g. ) I don't understand how to map to them from an at-rule page like @media (i.e. there's no at-rules property, as there is in mdn/data)

@wbamberg FWIW, webref is landing support for at-rules now, e.g https://github.com/w3c/webref/blob/07b36e04df4f20e65aaed3a33f091fe8428cdf4a/ed/css/css-fonts-5.json#L23

@wbamberg
Copy link
Collaborator Author

it looks like we can map at-rule descriptors, like, say, aspect-ratio, to syntax values using the descriptors property, but although we have the underlying syntax for at rules (e.g. ) I don't understand how to map to them from an at-rule page like @media (i.e. there's no at-rules property, as there is in mdn/data)

@wbamberg FWIW, webref is landing support for at-rules now, e.g https://github.com/w3c/webref/blob/07b36e04df4f20e65aaed3a33f091fe8428cdf4a/ed/css/css-fonts-5.json#L23

Thank you @dontcallmedom ! MDN is now fetching and rendering formal syntax for at-rules and at-rule descriptors -> mdn/content#22167 !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🧑‍🤝‍🧑 community contributions by our wonderful community dependencies Pull requests that update a dependency file enhancement Improves an existing feature. macros tracking issues related to kumascript macros 🚉 platform keeping the platform healthy
Projects
Development

Successfully merging this pull request may close these issues.

9 participants