241 lines
12 KiB
JavaScript
241 lines
12 KiB
JavaScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
(function (factory) {
|
|
if (typeof module === "object" && typeof module.exports === "object") {
|
|
var v = factory(require, exports);
|
|
if (v !== undefined) module.exports = v;
|
|
}
|
|
else if (typeof define === "function" && define.amd) {
|
|
define(["require", "exports", "../utils/markup"], factory);
|
|
}
|
|
})(function (require, exports) {
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.HTMLDataProvider = exports.browserNames = exports.BaselineImages = void 0;
|
|
exports.getMissingBaselineBrowsers = getMissingBaselineBrowsers;
|
|
exports.generateDocumentation = generateDocumentation;
|
|
const markup_1 = require("../utils/markup");
|
|
exports.BaselineImages = {
|
|
BASELINE_LIMITED: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTgiIGhlaWdodD0iMTAiIHZpZXdCb3g9IjAgMCA1NDAgMzAwIiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxzdHlsZT4KICAgIC5ncmF5LXNoYXBlIHsKICAgICAgZmlsbDogI0M2QzZDNjsgLyogTGlnaHQgbW9kZSAqLwogICAgfQoKICAgIEBtZWRpYSAocHJlZmVycy1jb2xvci1zY2hlbWU6IGRhcmspIHsKICAgICAgLmdyYXktc2hhcGUgewogICAgICAgIGZpbGw6ICM1NjU2NTY7IC8qIERhcmsgbW9kZSAqLwogICAgICB9CiAgICB9CiAgPC9zdHlsZT4KICA8cGF0aCBkPSJNMTUwIDBMMjQwIDkwTDIxMCAxMjBMMTIwIDMwTDE1MCAwWiIgZmlsbD0iI0YwOTQwOSIvPgogIDxwYXRoIGQ9Ik00MjAgMzBMNTQwIDE1MEw0MjAgMjcwTDM5MCAyNDBMNDgwIDE1MEwzOTAgNjBMNDIwIDMwWiIgY2xhc3M9ImdyYXktc2hhcGUiLz4KICA8cGF0aCBkPSJNMzMwIDE4MEwzMDAgMjEwTDM5MCAzMDBMNDIwIDI3MEwzMzAgMTgwWiIgZmlsbD0iI0YwOTQwOSIvPgogIDxwYXRoIGQ9Ik0xMjAgMzBMMTUwIDYwTDYwIDE1MEwxNTAgMjQwTDEyMCAyNzBMMCAxNTBMMTIwIDMwWiIgY2xhc3M9ImdyYXktc2hhcGUiLz4KICA8cGF0aCBkPSJNMzkwIDBMNDIwIDMwTDE1MCAzMDBMMTIwIDI3MEwzOTAgMFoiIGZpbGw9IiNGMDk0MDkiLz4KPC9zdmc+',
|
|
BASELINE_LOW: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTgiIGhlaWdodD0iMTAiIHZpZXdCb3g9IjAgMCA1NDAgMzAwIiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxzdHlsZT4KICAgIC5ibHVlLXNoYXBlIHsKICAgICAgZmlsbDogI0E4QzdGQTsgLyogTGlnaHQgbW9kZSAqLwogICAgfQoKICAgIEBtZWRpYSAocHJlZmVycy1jb2xvci1zY2hlbWU6IGRhcmspIHsKICAgICAgLmJsdWUtc2hhcGUgewogICAgICAgIGZpbGw6ICMyRDUwOUU7IC8qIERhcmsgbW9kZSAqLwogICAgICB9CiAgICB9CgogICAgLmRhcmtlci1ibHVlLXNoYXBlIHsKICAgICAgICBmaWxsOiAjMUI2RUYzOwogICAgfQoKICAgIEBtZWRpYSAocHJlZmVycy1jb2xvci1zY2hlbWU6IGRhcmspIHsKICAgICAgICAuZGFya2VyLWJsdWUtc2hhcGUgewogICAgICAgICAgICBmaWxsOiAjNDE4NUZGOwogICAgICAgIH0KICAgIH0KCiAgPC9zdHlsZT4KICA8cGF0aCBkPSJNMTUwIDBMMTgwIDMwTDE1MCA2MEwxMjAgMzBMMTUwIDBaIiBjbGFzcz0iYmx1ZS1zaGFwZSIvPgogIDxwYXRoIGQ9Ik0yMTAgNjBMMjQwIDkwTDIxMCAxMjBMMTgwIDkwTDIxMCA2MFoiIGNsYXNzPSJibHVlLXNoYXBlIi8+CiAgPHBhdGggZD0iTTQ1MCA2MEw0ODAgOTBMNDUwIDEyMEw0MjAgOTBMNDUwIDYwWiIgY2xhc3M9ImJsdWUtc2hhcGUiLz4KICA8cGF0aCBkPSJNNTEwIDEyMEw1NDAgMTUwTDUxMCAxODBMNDgwIDE1MEw1MTAgMTIwWiIgY2xhc3M9ImJsdWUtc2hhcGUiLz4KICA8cGF0aCBkPSJNNDUwIDE4MEw0ODAgMjEwTDQ1MCAyNDBMNDIwIDIxMEw0NTAgMTgwWiIgY2xhc3M9ImJsdWUtc2hhcGUiLz4KICA8cGF0aCBkPSJNMzkwIDI0MEw0MjAgMjcwTDM5MCAzMDBMMzYwIDI3MEwzOTAgMjQwWiIgY2xhc3M9ImJsdWUtc2hhcGUiLz4KICA8cGF0aCBkPSJNMzMwIDE4MEwzNjAgMjEwTDMzMCAyNDBMMzAwIDIxMEwzMzAgMTgwWiIgY2xhc3M9ImJsdWUtc2hhcGUiLz4KICA8cGF0aCBkPSJNOTAgNjBMMTIwIDkwTDkwIDEyMEw2MCA5MEw5MCA2MFoiIGNsYXNzPSJibHVlLXNoYXBlIi8+CiAgPHBhdGggZD0iTTM5MCAwTDQyMCAzMEwxNTAgMzAwTDAgMTUwTDMwIDEyMEwxNTAgMjQwTDM5MCAwWiIgY2xhc3M9ImRhcmtlci1ibHVlLXNoYXBlIi8+Cjwvc3ZnPg==',
|
|
BASELINE_HIGH: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTgiIGhlaWdodD0iMTAiIHZpZXdCb3g9IjAgMCA1NDAgMzAwIiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxzdHlsZT4KICAgIC5ncmVlbi1zaGFwZSB7CiAgICAgIGZpbGw6ICNDNEVFRDA7IC8qIExpZ2h0IG1vZGUgKi8KICAgIH0KCiAgICBAbWVkaWEgKHByZWZlcnMtY29sb3Itc2NoZW1lOiBkYXJrKSB7CiAgICAgIC5ncmVlbi1zaGFwZSB7CiAgICAgICAgZmlsbDogIzEyNTIyNTsgLyogRGFyayBtb2RlICovCiAgICAgIH0KICAgIH0KICA8L3N0eWxlPgogIDxwYXRoIGQ9Ik00MjAgMzBMMzkwIDYwTDQ4MCAxNTBMMzkwIDI0MEwzMzAgMTgwTDMwMCAyMTBMMzkwIDMwMEw1NDAgMTUwTDQyMCAzMFoiIGNsYXNzPSJncmVlbi1zaGFwZSIvPgogIDxwYXRoIGQ9Ik0xNTAgMEwzMCAxMjBMNjAgMTUwTDE1MCA2MEwyMTAgMTIwTDI0MCA5MEwxNTAgMFoiIGNsYXNzPSJncmVlbi1zaGFwZSIvPgogIDxwYXRoIGQ9Ik0zOTAgMEw0MjAgMzBMMTUwIDMwMEwwIDE1MEwzMCAxMjBMMTUwIDI0MEwzOTAgMFoiIGZpbGw9IiMxRUE0NDYiLz4KPC9zdmc+'
|
|
};
|
|
function getEntryBaselineImage(status) {
|
|
if (!status) {
|
|
return '';
|
|
}
|
|
let baselineImg;
|
|
switch (status?.baseline) {
|
|
case 'low':
|
|
baselineImg = exports.BaselineImages.BASELINE_LOW;
|
|
break;
|
|
case 'high':
|
|
baselineImg = exports.BaselineImages.BASELINE_HIGH;
|
|
break;
|
|
default:
|
|
baselineImg = exports.BaselineImages.BASELINE_LIMITED;
|
|
}
|
|
return ``;
|
|
}
|
|
function getEntryBaselineStatus(status, browsers) {
|
|
if (!status) {
|
|
return '';
|
|
}
|
|
if (status.baseline === false) {
|
|
const missingBrowsers = getMissingBaselineBrowsers(browsers);
|
|
let status = `Limited availability across major browsers`;
|
|
if (missingBrowsers) {
|
|
status += ` (Not fully implemented in ${missingBrowsers})`;
|
|
}
|
|
return status;
|
|
}
|
|
const baselineYear = status.baseline_low_date?.split('-')[0];
|
|
return `${status.baseline === 'low' ? 'Newly' : 'Widely'} available across major browsers (Baseline since ${baselineYear})`;
|
|
}
|
|
exports.browserNames = {
|
|
'C': {
|
|
name: 'Chrome',
|
|
platform: 'desktop'
|
|
},
|
|
'CA': {
|
|
name: 'Chrome',
|
|
platform: 'Android'
|
|
},
|
|
'E': {
|
|
name: 'Edge',
|
|
platform: 'desktop'
|
|
},
|
|
'FF': {
|
|
name: 'Firefox',
|
|
platform: 'desktop'
|
|
},
|
|
'FFA': {
|
|
name: 'Firefox',
|
|
platform: 'Android'
|
|
},
|
|
'S': {
|
|
name: 'Safari',
|
|
platform: 'macOS'
|
|
},
|
|
'SM': {
|
|
name: 'Safari',
|
|
platform: 'iOS'
|
|
}
|
|
};
|
|
const shortCompatPattern = /(E|FFA|FF|SM|S|CA|C|IE|O)([\d|\.]+)?/;
|
|
// TODO: Remove "as any" when tsconfig supports es2021+
|
|
const missingBaselineBrowserFormatter = new Intl.ListFormat("en", {
|
|
style: "long",
|
|
type: "disjunction",
|
|
});
|
|
/**
|
|
* Input is like [E12, FF28, FM28, C29, CM29, IE11, O16]
|
|
* Output is like `Safari`
|
|
*/
|
|
function getMissingBaselineBrowsers(browsers) {
|
|
if (!browsers) {
|
|
return '';
|
|
}
|
|
const missingBrowsers = new Map(Object.entries(exports.browserNames));
|
|
for (const shortCompatString of browsers) {
|
|
const match = shortCompatPattern.exec(shortCompatString);
|
|
if (!match) {
|
|
continue;
|
|
}
|
|
const browser = match[1];
|
|
missingBrowsers.delete(browser);
|
|
}
|
|
return missingBaselineBrowserFormatter.format(Object.values(Array.from(missingBrowsers.entries()).reduce((browsers, [browserId, browser]) => {
|
|
if (browser.name in browsers || browserId === 'E') {
|
|
browsers[browser.name] = browser.name;
|
|
return browsers;
|
|
}
|
|
// distinguish between platforms when applicable
|
|
browsers[browser.name] = `${browser.name} on ${browser.platform}`;
|
|
return browsers;
|
|
}, {})));
|
|
}
|
|
class HTMLDataProvider {
|
|
isApplicable() {
|
|
return true;
|
|
}
|
|
/**
|
|
* Currently, unversioned data uses the V1 implementation
|
|
* In the future when the provider handles multiple versions of HTML custom data,
|
|
* use the latest implementation for unversioned data
|
|
*/
|
|
constructor(id, customData) {
|
|
this.id = id;
|
|
this._tags = [];
|
|
this._tagMap = {};
|
|
this._valueSetMap = {};
|
|
this._tags = customData.tags || [];
|
|
this._globalAttributes = customData.globalAttributes || [];
|
|
this._tags.forEach(t => {
|
|
this._tagMap[t.name.toLowerCase()] = t;
|
|
});
|
|
if (customData.valueSets) {
|
|
customData.valueSets.forEach(vs => {
|
|
this._valueSetMap[vs.name] = vs.values;
|
|
});
|
|
}
|
|
}
|
|
getId() {
|
|
return this.id;
|
|
}
|
|
provideTags() {
|
|
return this._tags;
|
|
}
|
|
provideAttributes(tag) {
|
|
const attributes = [];
|
|
const processAttribute = (a) => {
|
|
attributes.push(a);
|
|
};
|
|
const tagEntry = this._tagMap[tag.toLowerCase()];
|
|
if (tagEntry) {
|
|
tagEntry.attributes.forEach(processAttribute);
|
|
}
|
|
this._globalAttributes.forEach(processAttribute);
|
|
return attributes;
|
|
}
|
|
provideValues(tag, attribute) {
|
|
const values = [];
|
|
attribute = attribute.toLowerCase();
|
|
const processAttributes = (attributes) => {
|
|
attributes.forEach(a => {
|
|
if (a.name.toLowerCase() === attribute) {
|
|
if (a.values) {
|
|
a.values.forEach(v => {
|
|
values.push(v);
|
|
});
|
|
}
|
|
if (a.valueSet) {
|
|
if (this._valueSetMap[a.valueSet]) {
|
|
this._valueSetMap[a.valueSet].forEach(v => {
|
|
values.push(v);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
});
|
|
};
|
|
const tagEntry = this._tagMap[tag.toLowerCase()];
|
|
if (tagEntry) {
|
|
processAttributes(tagEntry.attributes);
|
|
}
|
|
processAttributes(this._globalAttributes);
|
|
return values;
|
|
}
|
|
}
|
|
exports.HTMLDataProvider = HTMLDataProvider;
|
|
/**
|
|
* Generate Documentation used in hover/complete
|
|
* From `documentation` and `references`
|
|
*/
|
|
function generateDocumentation(item, settings = {}, doesSupportMarkdown) {
|
|
const result = {
|
|
kind: doesSupportMarkdown ? 'markdown' : 'plaintext',
|
|
value: ''
|
|
};
|
|
if (item.description && settings.documentation !== false) {
|
|
const normalizedDescription = (0, markup_1.normalizeMarkupContent)(item.description);
|
|
if (normalizedDescription) {
|
|
result.value += normalizedDescription.value;
|
|
}
|
|
}
|
|
if (item.status && settings.documentation !== false) {
|
|
if (result.value.length) {
|
|
result.value += `\n\n`;
|
|
}
|
|
const baselineStatus = getEntryBaselineStatus(item.status, item.browsers);
|
|
if (doesSupportMarkdown) {
|
|
result.value += `${getEntryBaselineImage(item.status)} _${baselineStatus}_`;
|
|
}
|
|
else {
|
|
result.value += baselineStatus;
|
|
}
|
|
}
|
|
if (item.references && item.references.length > 0 && settings.references !== false) {
|
|
if (result.value.length) {
|
|
result.value += `\n\n`;
|
|
}
|
|
if (doesSupportMarkdown) {
|
|
result.value += item.references.map(r => {
|
|
return `[${r.name}](${r.url})`;
|
|
}).join(' | ');
|
|
}
|
|
else {
|
|
result.value += item.references.map(r => {
|
|
return `${r.name}: ${r.url}`;
|
|
}).join('\n');
|
|
}
|
|
}
|
|
if (result.value === '') {
|
|
return undefined;
|
|
}
|
|
return result;
|
|
}
|
|
});
|