Complete residential site build with Docker Compose & Gitea Actions deployment

This commit is contained in:
CalebLewallen
2026-05-13 17:31:20 -04:00
parent f9c4e13a50
commit 3c22823f72
19354 changed files with 2097331 additions and 0 deletions
@@ -0,0 +1,2 @@
import { HTMLDataV1 } from '../../htmlLanguageTypes';
export declare const htmlData: HTMLDataV1;
File diff suppressed because one or more lines are too long
@@ -0,0 +1,77 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { HTMLDataProvider } from './dataProvider';
import { htmlData } from './data/webCustomData';
import * as arrays from '../utils/arrays';
export class HTMLDataManager {
constructor(options) {
this.dataProviders = [];
this.setDataProviders(options.useDefaultDataProvider !== false, options.customDataProviders || []);
}
setDataProviders(builtIn, providers) {
this.dataProviders = [];
if (builtIn) {
this.dataProviders.push(new HTMLDataProvider('html5', htmlData));
}
this.dataProviders.push(...providers);
}
getDataProviders() {
return this.dataProviders;
}
isVoidElement(e, voidElements) {
return !!e && arrays.binarySearch(voidElements, e.toLowerCase(), (s1, s2) => s1.localeCompare(s2)) >= 0;
}
getVoidElements(languageOrProviders) {
const dataProviders = Array.isArray(languageOrProviders) ? languageOrProviders : this.getDataProviders().filter(p => p.isApplicable(languageOrProviders));
const voidTags = [];
dataProviders.forEach((provider) => {
provider.provideTags().filter(tag => tag.void).forEach(tag => voidTags.push(tag.name));
});
return voidTags.sort();
}
isPathAttribute(tag, attr) {
// should eventually come from custom data
if (attr === 'src' || attr === 'href') {
return true;
}
const a = PATH_TAG_AND_ATTR[tag];
if (a) {
if (typeof a === 'string') {
return a === attr;
}
else {
return a.indexOf(attr) !== -1;
}
}
return false;
}
}
// Selected from https://stackoverflow.com/a/2725168/1780148
const PATH_TAG_AND_ATTR = {
// HTML 4
a: 'href',
area: 'href',
body: 'background',
blockquote: 'cite',
del: 'cite',
form: 'action',
frame: ['src', 'longdesc'],
img: ['src', 'longdesc'],
ins: 'cite',
link: 'href',
object: 'data',
q: 'cite',
script: 'src',
// HTML 5
audio: 'src',
button: 'formaction',
command: 'icon',
embed: 'src',
html: 'manifest',
input: ['src', 'formaction'],
source: 'src',
track: 'src',
video: ['src', 'poster']
};
@@ -0,0 +1,224 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { normalizeMarkupContent } from '../utils/markup';
export const 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 = BaselineImages.BASELINE_LOW;
break;
case 'high':
baselineImg = BaselineImages.BASELINE_HIGH;
break;
default:
baselineImg = BaselineImages.BASELINE_LIMITED;
}
return `![Baseline icon](${baselineImg})`;
}
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})`;
}
export const 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`
*/
export function getMissingBaselineBrowsers(browsers) {
if (!browsers) {
return '';
}
const missingBrowsers = new Map(Object.entries(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;
}, {})));
}
export 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;
}
}
/**
* Generate Documentation used in hover/complete
* From `documentation` and `references`
*/
export function generateDocumentation(item, settings = {}, doesSupportMarkdown) {
const result = {
kind: doesSupportMarkdown ? 'markdown' : 'plaintext',
value: ''
};
if (item.description && settings.documentation !== false) {
const normalizedDescription = 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;
}