Skip to content

Commit

Permalink
feat(macros/CSSSyntax): support at-rules and at-rule descriptors (#7322)
Browse files Browse the repository at this point in the history
* Support at-rules and at-rule descriptors on the formal syntax

* at-rules want all specs
  • Loading branch information
wbamberg authored Nov 8, 2022
1 parent f24093e commit f8ab999
Showing 1 changed file with 100 additions and 43 deletions.
143 changes: 100 additions & 43 deletions kumascript/macros/CSSSyntax.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -79,64 +79,39 @@ for (const spec of Object.values(parsedWebRef)) {
}
/**
* Get the formal syntax and properly formatted name for an item.
* Get the spec shortnames for an item, given:
* @param {string} itemName - the name of the item
* @param {string} itemType - this can only be "properties" or "atrules"
*/
function getNameAndSyntax() {
// get the item name from the page slug
let itemName = $0 || env.slug.split('/').pop().toLowerCase();
let itemSyntax;
switch (env["page-type"]) {
case "css-shorthand-property":
case "css-property":
itemSyntax = getPropertySyntax(itemName, parsedWebRef);
break;
case "css-type":
// some CSS data type slugs have a `_value` suffix
if (itemName.endsWith("_value")) {
itemName = itemName.replace("_value", "");
}
itemName = `<${itemName}>`;
// not all types have an entry in the syntax
if (valuespaces[itemName]) {
itemSyntax = valuespaces[itemName].value;
}
break;
case "css-function":
itemName = `<${itemName}()>`;
// not all functions have an entry in the syntax
if (valuespaces[itemName]) {
itemSyntax = valuespaces[itemName].value;
}
break;
}
return {
name: itemName,
syntax: itemSyntax
function getSpecsForItem(itemName, itemType) {
// Get all specs which list this item
const specsForItem = [];
for (const [shortname, data] of Object.entries(parsedWebRef)) {
const itemNames = Object.keys(data[itemType]);
if (itemNames.includes(itemName)) {
specsForItem.push(shortname);
}
}
return specsForItem;
}
/**
* Get the formal syntax for a property from the webref data, given:
* @param {string} propertyName - the name of the property
*/
function getPropertySyntax(propertyName) {
// 1) get all specs which list this property
let specsForProp = [];
for (const [shortname, data] of Object.entries(parsedWebRef)) {
const propNames = Object.keys(data.properties);
if (propNames.includes(propertyName)) {
specsForProp.push(shortname);
}
}
function getPropertySyntax(propertyName) {
// 1) Get all specs which list this property
let specsForProp = getSpecsForItem(propertyName, "properties");
// 2) If we have more than one spec, filter out specs that end "-n" where n is a number
if (specsForProp.length > 1) {
specsForProp = specsForProp.filter( specName => !(/-\d+$/.test(specName)) );
}
// 3) If we now have only one spec, return the syntax it lists
// 3) If we have only one spec, return the syntax it lists
if (specsForProp.length === 1) {
return parsedWebRef[specsForProp[0]].properties[propertyName].value;
}
// 4) If we still have > 1 spec, assume that:
// 4) If we have > 1 spec, assume that:
// - one of them is the base spec, which defines `values`,
// - the others define incremental additions as `newValues`
let syntax = '';
Expand All @@ -158,6 +133,88 @@ function getPropertySyntax(propertyName) {
return syntax;
}
/**
* Get the formal syntax for an at-rule from the webref data, given:
* @param {string} atRuleName - the name of the at-rule
*/
function getAtRuleSyntax(atRuleName) {
// An at-rule may appear in more than one spec: for example, if extra descriptors
// are defined in different specs. But we assume that the at-rule's own syntax,
// defined in the `value` property, only appears in one of them.
const specs = getSpecsForItem(atRuleName, "atrules");
for (const spec of specs) {
if (parsedWebRef[spec].atrules[atRuleName].value) {
return parsedWebRef[spec].atrules[atRuleName].value;
}
}
return '';
}
/**
* Get the formal syntax for an at-rule descriptor from the webref data, given:
* @param {string} atRuleDescriptorName - the name of the at-rule descriptor
*/
function getAtRuleDescriptorSyntax(atRuleDescriptorName) {
// We assume that the at-rule descriptor page is directly under
// the page for its at-rule.
const atRuleName = env.slug.split('/').at(-2);
const specs = getSpecsForItem(atRuleName, "atrules");
// Look through all the specs that define the at-rule, for the one
// that defines this descriptor.
for (const spec of specs) {
const atRule = parsedWebRef[spec].atrules[atRuleName];
for (const descriptor of atRule.descriptors) {
if (descriptor.name === atRuleDescriptorName) {
return descriptor.value;
}
}
}
return '';
}
/**
* Get the formal syntax and properly formatted name for an item.
*/
function getNameAndSyntax() {
// get the item name from the page slug
let itemName = $0 || env.slug.split('/').pop().toLowerCase();
let itemSyntax;
switch (env["page-type"]) {
case "css-shorthand-property":
case "css-property":
itemSyntax = getPropertySyntax(itemName);
break;
case "css-type":
// some CSS data type slugs have a `_value` suffix
if (itemName.endsWith("_value")) {
itemName = itemName.replace("_value", "");
}
itemName = `<${itemName}>`;
// not all types have an entry in the syntax
if (valuespaces[itemName]) {
itemSyntax = valuespaces[itemName].value;
}
break;
case "css-function":
itemName = `<${itemName}()>`;
// not all functions have an entry in the syntax
if (valuespaces[itemName]) {
itemSyntax = valuespaces[itemName].value;
}
break;
case "css-at-rule":
itemSyntax = getAtRuleSyntax(itemName);
break;
case "css-at-rule-descriptor":
itemSyntax = getAtRuleDescriptorSyntax(itemName);
break;
}
return {
name: itemName,
syntax: itemSyntax
}
}
/**
* Get the markup for a multiplier, including links to the value definition syntax.
*/
Expand Down

0 comments on commit f8ab999

Please sign in to comment.