Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions web-data/css/add-atrule-descriptors.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { listAll } from '@webref/css'

export async function addAtRuleDescriptors(atDirectives) {
await addMediaQueryAtRuleDescriptors(atDirectives.find((directive) => directive.name === '@media'))
return atDirectives
}

/**
* @typedef {{name: string, href: string, value: string, type: string, values?: SpecDescriptorValue[]}} SpecDescriptor
* @typedef {{name: string, prose: string, href: string, type: string, value: string}} SpecDescriptorValue
* @typedef {{name: string, description?: string, references: IReference[], syntax: string, type: string, values: IValueData[]}} Descriptor
* @typedef {{name: string, description?: string, references: IReference[]}} IValueData
* @typedef {{name: string, url: string}} IReference
*/

async function addMediaQueryAtRuleDescriptors(atDirective) {
const mediaQueries = (await listAll())['mediaqueries-5']
/** @type {SpecDescriptor[]} */
const specDescriptors = mediaQueries.atrules.find((obj) => obj.name === '@media').descriptors
/** @type {Descriptor[]} */
const outDescriptors = []
for (const descriptor of specDescriptors) {
outDescriptors.push({
name: descriptor.name,
references: [{ name: 'W3C Reference', url: descriptor.href }],
type: descriptor.type,
syntax: descriptor.value,
values: descriptor.values?.map((value) => ({
name: value.name,
description: value.prose,
references: [{ name: 'W3C Reference', url: value.href }],
})),
})
}
atDirective.descriptors = outDescriptors
}
29 changes: 20 additions & 9 deletions web-data/css/generateData.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { addMDNAtDirectives, addMDNPseudoElements, addMDNPseudoSelectors } from
import { addBrowserCompatDataToProperties, addMDNReferences, browserNames } from './mdn/mdn-browser-compat-data-importer.mjs';
import { applyRelevance } from './chromestatus/applyRelevance.mjs';
import { computeBaseline } from 'compute-baseline';
import { addAtRuleDescriptors } from './add-atrule-descriptors.mjs';

const { readFile, writeFile } = fs.promises;

Expand Down Expand Up @@ -242,14 +243,14 @@ function getValues(valArr, restriction, ruleName) {
}
}
var vals = valArr
.map(function (v) {
.map(function(v) {
return {
name: v.$.name,
desc: v.desc,
browsers: v.$.browsers !== 'all' ? v.$.browsers : void 0
}
})
.filter(function (v) {
.filter(function(v) {
if (v.browsers === 'none') {
return false
}
Expand All @@ -261,7 +262,7 @@ function getValues(valArr, restriction, ruleName) {

var moreColors = {}

vals = vals.filter(function (v) {
vals = vals.filter(function(v) {
if (typeof colorsCopy[v.name] === 'string') {
delete colorsCopy[v.name]
return false
Expand Down Expand Up @@ -307,7 +308,7 @@ function toSource(object, keyName) {
}
var result = []
var entryArr = object.css[keyName].entry
entryArr.forEach(function (e) {
entryArr.forEach(function(e) {
if (e.$.browsers === 'none') {
return
}
Expand Down Expand Up @@ -336,6 +337,7 @@ async function process() {
const data = await readFile(path.resolve(__dirname, schemaFileName));
const result = JSON.parse(data.toString());
let atDirectives = toSource(result, 'atDirectives');
atDirectives = await addAtRuleDescriptors(atDirectives)
atDirectives = await addMDNAtDirectives(atDirectives);

let pseudoClasses = toSource(result, 'pseudoClasses');
Expand All @@ -360,7 +362,12 @@ async function process() {
}

customDataObject.properties.forEach(processEntry)
customDataObject.atDirectives.forEach(processEntry)
for (const directive of customDataObject.atDirectives) {
processEntry(directive)
for (const descriptor of directive.descriptors || []) {
processEntry(descriptor)
}
}
customDataObject.pseudoClasses.forEach(processEntry)
customDataObject.pseudoElements.forEach(processEntry)

Expand Down Expand Up @@ -419,13 +426,17 @@ function processEntry(entry) {
* Todo@Pine: Change MDN data generation so this yields new entry
*/
function convertEntry(entry) {
entry.description = entry.desc
delete entry.desc
if ('desc' in entry) {
entry.description = entry.desc
delete entry.desc
}

if (entry.values) {
entry.values.forEach(v => {
v.description = v.desc
delete v.desc
if ('desc' in v) {
v.description = v.desc
delete v.desc
}

if (v.browsers) {
if (v.browsers === 'all') {
Expand Down
34 changes: 26 additions & 8 deletions web-data/css/mdn/mdn-browser-compat-data-importer.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import bcd from '@mdn/browser-compat-data' with { type: 'json' };
export function addBrowserCompatDataToProperties(atdirectives, pseudoclasses, pseudoelements, properties) {
atdirectives.forEach(item => {
addCompatData(item, 'at-rules', item.name.slice(1));
for (const descriptor of item.descriptors || []) {
addCompatData(descriptor, 'at-rules', item.name.slice(1), descriptor.name);
}
});

pseudoclasses.forEach(item => {
Expand All @@ -33,19 +36,31 @@ export function addBrowserCompatDataToProperties(atdirectives, pseudoclasses, ps
});
}

function addCompatData(item, namespace, featureName) {
function addCompatData(item, namespace, featureName, subField) {
if (!(featureName in bcd.css[namespace])) {
return;
}

const matchingBCDItem = bcd.css[namespace][featureName];
item.bcdKey = `css.${namespace}.${featureName}`;
let matchingBCDItem = bcd.css[namespace][featureName];
if (subField) {
matchingBCDItem = matchingBCDItem[subField]
}

if (!(matchingBCDItem)) {
return;
}

if (subField) {
item.bcdKey = `css.${namespace}.${featureName}.${subField}`;
} else {
item.bcdKey = `css.${namespace}.${featureName}`;
}
addBCDToBrowsers(item, matchingBCDItem);
}

export function addMDNReferences(atdirectives, pseudoclasses, pseudoelements, properties) {
const addReference = (item, matchingItem) => {
if (matchingItem.__compat && matchingItem.__compat.mdn_url) {
if (matchingItem?.__compat?.mdn_url) {
if (!item.references) {
item.references = [];
}
Expand All @@ -60,6 +75,9 @@ export function addMDNReferences(atdirectives, pseudoclasses, pseudoelements, pr
if (bcd.css['at-rules'][item.name.slice(1)]) {
const matchingBCDItem = bcd.css['at-rules'][item.name.slice(1)];
addReference(item, matchingBCDItem);
for (const descriptor of item.descriptors || []) {
addReference(descriptor, matchingBCDItem[descriptor.name]);
}
}
});

Expand Down Expand Up @@ -159,7 +177,7 @@ export function supportToShortCompatString(support, browserAbbrev) {
}

if (version_added) {
if (typeof(version_added) === 'string') {
if (typeof (version_added) === 'string') {
if (version_added.startsWith('≤')) {
version_added = version_added.substring(1);
}
Expand All @@ -180,10 +198,10 @@ function isSupported(support) {
}

if (version_added) {
if (typeof(version_added) === 'boolean') {
if (typeof (version_added) === 'boolean') {
return version_added;
} else if (typeof(version_added) === 'string') {
if (typeof(parseInt(version_added)) === 'number') {
} else if (typeof (version_added) === 'string') {
if (typeof (parseInt(version_added)) === 'number') {
return true;
}
}
Expand Down
2 changes: 1 addition & 1 deletion web-data/css/mdn/mdn-data-importer.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ export async function addMDNProperties(vscProperties) {

if (missingDocumentation.length) {
const fetchedDocs = ['{'];
console.log('add to mdn-documentation.ts (propertyDescriptions):');
console.log('add to mdn-documentation.mjs (propertyDescriptions):');
for (let prop of missingDocumentation) {
const doc = await fetchDocFromMDN(prop, propertyMap[prop]?.atRule);
fetchedDocs.push(` '${prop}': \`${doc ?? ''}\`,`);
Expand Down
53 changes: 40 additions & 13 deletions web-data/css/mdn/mdn-data-selector-importer.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import mdnData from 'mdn-data';
import mdnCompatData from '@mdn/browser-compat-data' with { type: 'json' };
import { abbreviateStatus } from './mdn-data-importer.mjs';
import { pseudoSelectorDescriptions, pseudoElementDescriptions, fetchDocFromMDN, atDirectiveDescriptions } from './mdn-documentation.mjs';
import { pseudoSelectorDescriptions, pseudoElementDescriptions, fetchDocFromMDN, atDirectiveDescriptions, atDirectiveDescriptorDescriptions } from './mdn-documentation.mjs';

export async function addMDNPseudoElements(vscPseudoElements) {
const mdnSelectors = mdnData.css.selectors;
Expand All @@ -26,21 +26,21 @@ export async function addMDNPseudoElements(vscPseudoElements) {
!allPseudoElementNames.includes(selectorName) &&
!allPseudoElementNames.includes(selectorName + '()')
) {
const desc = pseudoElementDescriptions[selectorName] || '';
if (!desc) {
const description = pseudoElementDescriptions[selectorName] || '';
if (!description) {
missingDocumentation.push(selectorName);
}
allPseudoElements.push({
name: selectorName,
desc,
description,
status: abbreviateStatus(selector, mdnCompatProperties[selectorName])
});
}
}
}
if (missingDocumentation.length) {
const fetchedDocs = ['{'];
console.log('add to mdn-documentation.ts (pseudoElementDescriptions):');
console.log('add to mdn-documentation.mjs (pseudoElementDescriptions):');
for (let prop of missingDocumentation) {
const doc = await fetchDocFromMDN(prop.replace(/::/, '_doublecolon_'), undefined);
fetchedDocs.push(` '${prop}': \`${doc ?? ''}\`,`);
Expand Down Expand Up @@ -77,21 +77,21 @@ export async function addMDNPseudoSelectors(vscPseudoClasses) {
!allPseudoSelectorNames.includes(selectorName) &&
!allPseudoSelectorNames.includes(selectorName + '()')
) {
const desc = pseudoSelectorDescriptions[selectorName] || '';
if (!desc) {
const description = pseudoSelectorDescriptions[selectorName] || '';
if (!description) {
missingDocumentation.push(selectorName);
}

allPseudoSelectors.push({
name: selectorName,
desc,
description,
status: abbreviateStatus(selector, mdnCompatProperties[selectorName])
});
}
}
}
if (missingDocumentation.length) {
console.log('add to mdn-documentation.ts (pseudoSelectorDescriptions):');
console.log('add to mdn-documentation.mjs (pseudoSelectorDescriptions):');
const fetchedDocs = ['{'];
for (let prop of missingDocumentation) {
const doc = await fetchDocFromMDN(prop.replace(/:/, '_colon_'), undefined);
Expand All @@ -112,21 +112,21 @@ export async function addMDNAtDirectives(atDirectives) {

for (const name of Object.keys(mdnAtRules)) {
if (!allAtDirectiveNames.includes(name)) {
const desc = atDirectiveDescriptions[name] || '';
if (!desc) {
const description = atDirectiveDescriptions[name] || '';
if (!description) {
missingDocumentation.push(name);
}

allAtDirectives.push({
name: name,
desc: desc,
description,
browsers: undefined
});
}
}

if (missingDocumentation.length) {
console.log('add to mdn-documentation.ts (atDirectiveDescriptions):');
console.log('add to mdn-documentation.mjs (atDirectiveDescriptions):');
const fetchedDocs = ['{'];
for (let prop of missingDocumentation) {
const doc = await fetchDocFromMDN(prop.replace(/:/, '_colon_'), undefined);
Expand All @@ -136,5 +136,32 @@ export async function addMDNAtDirectives(atDirectives) {
console.log(fetchedDocs.join('\n'));
}

for (const directive of allAtDirectives) {
const missingDocumentation = [];
if (directive.descriptors) {
const descriptorDescriptions = atDirectiveDescriptorDescriptions[directive.name] || {}
for (const descriptor of directive.descriptors) {
const description = descriptorDescriptions[descriptor.name]
if (description !== undefined) {
descriptor.description = description
descriptor.status = abbreviateStatus(descriptor.name, mdnCompatData.css['at-rules'][directive.name.slice(1)]?.[descriptor.name])
} else {
missingDocumentation.push(descriptor.name)
}
}
}

if (missingDocumentation.length) {
console.log(`add to mdn-documentation.mjs (atDirectiveDescriptorDescriptions['${directive.name}']):`);
const fetchedDocs = ['{'];
for (const descriptor of missingDocumentation) {
const doc = await fetchDocFromMDN(descriptor, directive.name);
fetchedDocs.push(` '${descriptor}': \`${doc ?? ''}\`,`);
}
fetchedDocs.push('}');
console.log(fetchedDocs.join('\n'));
}
}

return allAtDirectives;
}
47 changes: 46 additions & 1 deletion web-data/css/mdn/mdn-documentation.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -398,4 +398,49 @@ export const atDirectiveDescriptions = {
'@view-transition': `The @view-transition CSS at-rule is used to opt in the current and destination documents to undergo a view transition, in the case of a cross-document navigation.`,
};


export const atDirectiveDescriptorDescriptions = {
'@media': {
'width': `The width CSS media feature can be used to test the width of the viewport (or the page box, for paged media).`,
'height': `The height CSS media feature can be used to apply styles based on the height of the viewport (or the page box, for paged media).`,
'aspect-ratio': `The aspect-ratio CSS media feature can be used to test the aspect ratio of the viewport.`,
'orientation': `The orientation CSS media feature can be used to test the orientation of the viewport (or the page box, for paged media).`,
'overflow-block': `The overflow-block CSS media feature can be used to test how the output device handles content that overflows the initial containing block along the block axis.`,
'overflow-inline': `The overflow-inline CSS media feature can be used to test how the output device handles content that overflows the initial containing block along the inline axis.`,
'horizontal-viewport-segments': ``,
'vertical-viewport-segments': ``,
'display-mode': `The display-mode CSS media feature can be used to test whether a web app is being displayed in a normal browser tab or in some alternative way, such as a standalone app or fullscreen mode.`,
'resolution': `The resolution CSS media feature can be used to test the pixel density of the output device.`,
'scan': `The scan CSS media feature is used to apply CSS styles based on the scanning process of the output device.`,
'grid': `The grid CSS media feature can be used to test whether the output device uses a grid-based screen.`,
'update': `The update CSS media feature can be used to test how frequently (if at all) the output device is able to modify the appearance of content once rendered.`,
'environment-blending': ``,
'color': `The color CSS media feature can be used to test the number of bits per color component (red, green, blue) of the output device.`,
'color-index': `The color-index CSS media feature can be used to test the number of entries in the output device's color lookup table.`,
'monochrome': `The monochrome CSS media feature can be used to test the number of bits per pixel in the monochrome frame buffer of the output device.`,
'color-gamut': `The color-gamut CSS media feature is used to apply CSS styles based on the approximate range of color gamut supported by the user agent and the output device.`,
'dynamic-range': `The dynamic-range CSS media feature can be used to test the combination of brightness, contrast ratio, and color depth that are supported by the user agent and the output device.`,
'inverted-colors': `The inverted-colors CSS media feature is used to test if the user agent or the underlying operating system has inverted all colors.`,
'pointer': `The pointer CSS media feature tests whether the user has a pointing device (such as a mouse), and if so, how accurate the primary pointing device is.`,
'hover': `The hover CSS media feature can be used to test whether the user's primary input mechanism can hover over elements.`,
'any-pointer': `The any-pointer CSS media feature tests whether the user has any pointing device (such as a mouse), and if so, how accurate it is.`,
'any-hover': `The any-hover CSS media feature can be used to test whether any available input mechanism can hover over elements.`,
'nav-controls': ``,
'video-color-gamut': ``,
'video-dynamic-range': `The video-dynamic-range CSS media feature can be used to test the combination of brightness, contrast ratio, and color depth that are supported by the video plane of the user agent and the output device.`,
'scripting': `The scripting CSS media feature can be used to test whether scripting (such as JavaScript) is available.`,
'prefers-reduced-motion': `The prefers-reduced-motion CSS media feature is used to detect if a user has enabled a setting on their device to minimize the amount of non-essential motion. The setting is used to convey to the browser on the device that the user prefers an interface that removes, reduces, or replaces motion-based animations.`,
'prefers-reduced-transparency': `The prefers-reduced-transparency CSS media feature is used to detect if a user has enabled a setting on their device to reduce the transparent or translucent layer effects used on the device. Switching on such a setting can help improve contrast and readability for some users.`,
'prefers-contrast': `The prefers-contrast CSS media feature is used to detect whether the user has requested the web content to be presented with a lower or higher contrast.`,
'forced-colors': `The forced-colors CSS media feature is used to detect if the user agent has enabled a forced colors mode where it enforces a user-chosen limited color palette on the page. An example of a forced colors mode is Windows High Contrast mode.`,
'prefers-color-scheme': `The prefers-color-scheme CSS media feature is used to detect if a user has requested light or dark color themes.`,
'prefers-reduced-data': `The prefers-reduced-data CSS media feature is used to detect if the user has requested the web content that consumes less internet traffic.`,
'device-width': `The device-width CSS media feature can be used to test the width of an output device's rendering surface.`,
'device-height': `The device-height CSS media feature can be used to test the height of an output device's rendering surface.`,
'device-aspect-ratio': `The device-aspect-ratio CSS media feature can be used to test the width-to-height aspect ratio of an output device.`,
'horizontal-viewport-segments': ``,
'vertical-viewport-segments': ``,
'environment-blending': ``,
'nav-controls': ``,
'video-color-gamut': ``,
},
}
Loading