<%
/*
Displays general information about a CSS property or descriptor
$0 - property/descriptor name - defaults to the slug name
$1 - @-rule - defaults to the @-rule within the URL
*/
var slug = env.slug;
var name = $0 || (slug ? slug.split("/").pop().toLowerCase() :
"preview-wiki-content");
var atRule = $1;
var data = string.deserialize(template("CSSData"));
var formattedError = "<span style=\"color:red;\">$1$</span>";
var commonLocalStrings = string.deserialize(template("L10n:Common"));
var locale = env.locale;
var escapeQuotes = mdn.escapeQuotes;
var localize = mdn.getLocalString;
var localizeString = mdn.localString;
var replacePlaceholders = mdn.replacePlaceholders;
var localWiki = wiki;
var currentPage = page;
var cssLocalStrings = string.deserialize(template("L10n:CSS"));
var localStrings = string.deserialize(template("L10n:CSSData"));
/*
Creates a link to another API, e.g. a CSS property or SVG element
This function is used as a workaround for not being able to call other
templates like 'cssxref' from within functions (see https://bugzil.la/939214)
apiName - Name of the API to link to
area - Area of the API (i.e. CSS, SVG, etc.)
linkName - String to use as link label
*/
function createLink(apiName, area, linkName) {
var formattedLinkName = linkName || apiName;
var url = "/" + locale + "/docs/Web/" + (area || "CSS") + "/" + apiName;
var thisPage = localWiki.getPage(url);
if (currentPage.hasTag(thisPage, "CSS Function")) {
formattedLinkName += "()";
} else if (currentPage.hasTag(thisPage, "CSS Data Type") ||
currentPage.hasTag(thisPage, "Element")) {
formattedLinkName = "<" + formattedLinkName + ">";
}
var summary = (thisPage && thisPage.summary) ?
escapeQuotes(thisPage.summary) :
localize(commonLocalStrings, "summary");
return "<a href=\"" + url + "\"" +
(summary ? " title=\"" + summary + "\"" : "") + "><code>" +
formattedLinkName + "</code></a>";
}
/*
Parses all macros within a string
string - String to parse
*/
function parseMacros(string) {
if (string === undefined) {
return undefined;
}
var apiName = "";
var area = "";
var parsedString = string;
parsedString = parsedString.replace(/\{\{(.+?)(?:\((.+?)\))?\}\}/g,
function (match, macroName, paramsString) {
var params = paramsString ? paramsString.split(/, ?/) : [];
params.forEach(function(param, index, params) {
params[index] = params[index].toLowerCase().slice(1, -1);
});
var apiName = (params.length !== 0 ? params[0] : "");
switch (macroName.toLowerCase()) {
case "xref_csslength":
apiName = "length";
area = "CSS";
break;
case "xref_cssangle":
apiName = "angle";
area = "CSS";
break;
case "svgelement":
area = "SVG/Element";
break;
default:
area = "CSS";
}
return createLink(apiName, area, params[1]);
}
);
return parsedString;
}
/*
Appends information about to which pseudo-elements a CSS property applies to
the output to which normal elements it applies
output - Current value output
property - CSS info item name
cssInfo - Structure containing information about a CSS property
*/
function addAdditionalAppliesToOutput(output, property, cssInfo) {
if (property !== "appliesto" || !cssInfo.hasOwnProperty("alsoAppliesTo")) {
return output;
}
var additionalApplies = "";
// Remove '::placeholder' from array to avoid displaying it,
// because it's not standardized yet
var placeholderIndex = cssInfo.alsoAppliesTo.indexOf("::placeholder");
if (placeholderIndex !== -1) {
cssInfo.alsoAppliesTo.splice(placeholderIndex, 1);
}
// In case there are no items left, the output is returned unchanged
if (cssInfo.alsoAppliesTo.length === 0) {
return output;
}
cssInfo.alsoAppliesTo.forEach(function(element, index, elements) {
additionalApplies += "{{cssxref(\"" + element + "\")}}";
if (index < elements.length - 2) {
additionalApplies += localize(localStrings, "listSeparator");
} else if (index < elements.length - 1) {
additionalApplies += localize(localStrings, "andInEnumeration");
}
});
return replacePlaceholders(localize(localStrings, "applyingToMultiple"),
[output, additionalApplies]);
}
/*
Parses all macros within a string
string - String to parse
*/
function getValueOutput(cssInfo, property, atRule) {
if (property === "relatedAtRule") {
var url = "/" + locale + "/docs/Web/CSS/" + atRule;
var page = localWiki.getPage(url);
var summary = (page && page.summary) ? escapeQuotes(page.summary) :
localize(commonLocalStrings, "summary");
return "<a href=\"/" + locale + "/docs/Web/CSS/" + atRule +
"\" title=\"" + summary + "\"><code>" + atRule + "</code></a>";
}
var value = cssInfo[property];
if (typeof value === "string") {
var propMatches = value.match(/^'(.+?)'$/);
if (propMatches) {
return getValueOutput(data.properties[propMatches[1]], property);
} else {
if (property === "initial" && value[0] === "<") {
return value;
} else {
var keywords = value.split(", ");
var replacedKeywords = keywords.map(function(keyword) {
return localize(localStrings, keyword);
});
var output = addAdditionalAppliesToOutput(
replacedKeywords.join(", "), property, cssInfo);
return parseMacros(output);
}
}
} else if (Array.isArray(value)) {
var output = localize(localStrings, "asLonghands") + "<br/>" +
"<ul>";
value.forEach(function(longhand) {
output += "<li>{{cssxref(\"" + longhand + "\")}}: " +
(data.properties.hasOwnProperty(longhand) ?
getValueOutput(data.properties[longhand], property) :
replacePlaceholders(formattedError,
[localize(cssLocalStrings, "missing")])) +
"</li>";
});
output += "</ul>";
return parseMacros(addAdditionalAppliesToOutput(output, property,
cssInfo));
} else if (typeof value === "object") {
var note = value.note || "";
var output = "";
if (property === "animatable" && value.hasOwnProperty("as") &&
value.as !== "yes") {
var animatableValues = value.as.split(" ");
var parsedAnimtableValues =
animatableValues.map(function(animatableValue) {
var localizedString = localize(localStrings,
animatableValue);
if (animatableValue === "lpc") {
localizedString = replacePlaceholders(localizedString,
[localize(localStrings, "length")]);
note = localize(localStrings, "lpcNote") + note;
}
return localizedString;
});
output = replacePlaceholders(localize(localStrings, "yesAs"),
[parsedAnimtableValues.join(localize(localStrings,
"listSeparator")), note]);
} else {
output = localizeString(value);
}
return parseMacros(addAdditionalAppliesToOutput(output, property,
cssInfo));
} else if (typeof value === "boolean") {
return localize(localStrings, value ? "yes" : "no");
} else if (typeof value === "undefined") {
return replacePlaceholders(formattedError, [localize(cssLocalStrings,
"missing")]);
}
return parseMacros(value);
}
var cssInfo = null;
if (!atRule) {
var matches = null;
if (slug) {
matches = slug.match(/\/CSS\/(@.+?)(?=\/)/);
}
if (matches) {
atRule = matches[1];
}
}
if (name !== "preview-wiki-content") {
if (atRule) {
if (data.atRules[atRule] && data.atRules[atRule].descriptors) {
cssInfo = data.atRules[atRule].descriptors[name];
}
} else if (data.properties[name]) {
cssInfo = data.properties[name];
}
}
var result = "";
if (name === "preview-wiki-content") {
result = "<span style=\"color:red;\">CSS info in preview not " +
"available</span>";
} else if (cssInfo) {
result = "<table class=\"properties\">" +
"<tbody>";
var properties = [];
if (atRule) {
properties = properties.concat({
name: "relatedAtRule",
label: localize(localStrings, "relatedAtRule")
});
}
properties = properties.concat({
name: "initial",
label: template("Xref_cssinitial")
});
if (!atRule) {
properties = properties.concat({
name: "appliesto",
label: localize(localStrings, "appliesTo")
});
}
if (cssInfo.hasOwnProperty("inherited")) {
properties = properties.concat({
name: "inherited",
label: template("Xref_cssinherited")
});
}
if (cssInfo.percentages !== "no") {
properties = properties.concat({
name: "percentages",
label: localize(localStrings, "percentages")
});
}
properties = properties.concat({
name: "media",
label: localize(localStrings, "media")
},
{
name: "computed",
label: template("Xref_csscomputed")
});
if (!atRule) {
properties = properties.concat({
name: "animatable",
label: localize(localStrings, "animatable")
});
}
properties = properties.concat({
name: "order",
label: localize(localStrings, "canonicalOrder")
});
if (cssInfo.stacking) {
properties = properties.concat({
name: "stacking",
label: localize(localStrings, "createsStackingContext")
});
}
properties.forEach(function(property) {
result += "<tr>" +
"<th scope=\"row\">" + property.label + "</th><td>" +
getValueOutput(cssInfo, property.name, atRule) + "</td>";
});
result += "</tbody>" +
"</table>";
} else {
result = replacePlaceholders(formattedError,
[localize(cssLocalStrings, "missing")]);
}
%><%- result %>
Search for pages that use Template:cssinfo to see example use cases and how many pages use this macro.
Document Tags and Contributors
Last updated by:
Sebastianz,