# Pull Request

## 📖 Description

<!--- Provide some background and a description of your work. -->
This PR adds the documentation site into the `main` branch. In future, `gh-pages` branch will be used for the generated site.

##  Checklist

### General

<!--- Review the list and put an x in the boxes that apply. -->

- [ ] I have added tests for my changes.
- [x] I have tested my changes.
- [x] I have updated the project documentation to reflect my changes.
This commit is contained in:
Jane Chu 2022-04-18 17:22:12 -07:00 коммит произвёл GitHub
Родитель db6f91562a
Коммит a77bc0ba00
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
47 изменённых файлов: 8086 добавлений и 36 удалений

2377
package-lock.json сгенерированный

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -11,7 +11,8 @@
"workspaces": [
"./packages/fast-tooling",
"./packages/fast-tooling-react",
"./packages/fast-tooling-wasm"
"./packages/fast-tooling-wasm",
"./website"
],
"repository": {
"type": "git",

17
website/.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,17 @@
# Dependencies
/node_modules
# Production
/dist
/www
# Misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

24
website/CONTRIBUTING.md Normal file
Просмотреть файл

@ -0,0 +1,24 @@
# Contributing
This website is a static website, it contains two separate generation methods, a front page which is created using webpack, and documentation pages created from the build script located in `build/docs.js` which leverages markdown.
Both portions of the site contain a `templates/` folder, which is used by both webpack and the `build/docs.js` file to construct the front page and the documentation respectively.
## Adding a document
When a new markdown file is added, be sure to include it in the `docs/sidebar.js`.
## Removing a document
When removing a markdown file, be sure to remove any reference to it from the `docs/sidebar.js`.
## Major versioning
When contributing a new version:
1. Add the version for the package in the `docs/versions.json`
2. Add the versioned folder `docs/{package-name}/{version}`
3. Update the sidebar versions in `docs/sidebar.js`
## Updating styles
The styles are globally applied to the front page and the documentation, they can be found in `src/templates/style/index.html`.

3
website/README.md Normal file
Просмотреть файл

@ -0,0 +1,3 @@
# Website
This is the website for the FAST Tooling project.

Просмотреть файл

@ -0,0 +1,2 @@
const ghPagesBaseUrl = "https://microsoft.github.io/fast-tooling";
export { ghPagesBaseUrl };

313
website/build/docs.js Normal file
Просмотреть файл

@ -0,0 +1,313 @@
import sidebar from "../docs/sidebar.js";
import path from "path";
import fs from "fs-extra";
import { marked } from "marked";
import { template as templateResolver } from "lodash-es";
import versions from "../docs/versions.json";
import { ghPagesBaseUrl } from "./constants.js";
const __dirname = process.cwd();
const baseUrl = process.argv.includes("gh-pages") ? ghPagesBaseUrl : "";
const docsDir = path.resolve(__dirname, "docs");
const outDir = path.resolve(__dirname, "www/docs");
const appDir = path.resolve(__dirname, "src");
const toolbarTemplate = path.resolve(appDir, "templates/toolbar/index.html");
const footerTemplate = path.resolve(appDir, "templates/footer/index.html");
const styleTemplate = path.resolve(appDir, "templates/style/index.html");
const metaTemplate = path.resolve(appDir, "templates/meta/index.html");
const categoryTemplate = path.resolve(docsDir, "templates/category/index.html");
const sidebarTemplate = path.resolve(docsDir, "templates/sidebar/index.html");
const versionTemplate = path.resolve(docsDir, "templates/version/index.html");
const type = {
category: "category",
doc: "doc",
};
/**
* Converts a markdown file to an html string
*
* @param {string} markdownPath
* @param {string} htmlPath
* @return Promise<string>
*/
function getHTMLStringFromMarkdownPath(markdownPath, htmlPath) {
return new Promise((resolve, reject) => {
fs.ensureDir(path.resolve(outDir, htmlPath))
.then(() => {
fs.readFile(path.resolve(docsDir, markdownPath), "utf8", (err, data) => {
if (err) {
throw err;
}
resolve(marked.parse(data));
});
})
.catch(err => {
reject(err);
});
});
}
/**
* Returns an object with `version` and `package` strings if a path is tied to
* a specific version, otherwise returns null.
*
* @param {string} path
* @returns null | object
*/
function getDocumentVersionAndPackageName(path) {
const pathItems = path.split("/");
const foundVersion = pathItems.findIndex(pathItem => {
return pathItem.match(/\d+\.x/);
});
if (foundVersion !== -1) {
return {
version: pathItems[foundVersion],
package: `@microsoft/${pathItems[foundVersion - 1]}`,
};
}
return null;
}
/**
* Converts a document from markdown to HTML
*
* @param {object} documentationItem
* @param {string} template
* @returns Promise
*/
function convertDocument(documentationItem, template, isVersionDoc) {
return new Promise((resolve, reject) => {
getHTMLStringFromMarkdownPath(
path.resolve(docsDir, `${documentationItem.path}.md`),
documentationItem.path
)
.then(html => {
const versionAndPackageName = getDocumentVersionAndPackageName(
documentationItem.path
);
let versionInfo = null;
if (versionAndPackageName !== null) {
versionInfo = {
package: versionAndPackageName.package,
docVersion: versionAndPackageName.version,
otherAvailableVersions: versions[
versionAndPackageName.package
].versions
.filter(value => {
return value !== versionAndPackageName.version;
})
.reduce((previousValue, nextValue) => {
previousValue.push({
path: documentationItem.path.replace(
versionAndPackageName.version,
nextValue
),
label: nextValue,
});
return previousValue;
}, []),
};
}
const docFile = {
type: type.doc,
path: documentationItem.path,
html: templateResolver(template)({
htmlWebpackPlugin: {
options: {
content: html,
toolbarTemplate: templateResolver(
fs.readFileSync(toolbarTemplate, "utf8")
)({
baseUrl,
}),
footerTemplate: templateResolver(
fs.readFileSync(footerTemplate, "utf8")
)(),
styleTemplate: fs.readFileSync(styleTemplate, "utf8"),
metaTemplate: templateResolver(
fs.readFileSync(metaTemplate, "utf8")
)({
baseUrl,
}),
sidebar: templateResolver(
fs.readFileSync(sidebarTemplate, "utf8")
)({
sidebar,
currentPath: documentationItem.path,
baseUrl,
}),
versionInfo:
versionInfo !== null
? templateResolver(
fs.readFileSync(versionTemplate, "utf8")
)({
versionInfo,
baseUrl,
})
: null,
baseUrl,
},
},
}),
};
fs.ensureDir(path.resolve(outDir, docFile.path))
.then(() => {
fs.writeFileSync(
path.resolve(outDir, docFile.path, "index.html"),
docFile.html
);
})
.finally(() => {
resolve();
})
.catch(err => {
reject(err);
});
if (versionInfo && versionInfo.otherAvailableVersions && !isVersionDoc) {
writeToHTML(
versionInfo.otherAvailableVersions.reduce(
(previousValue, nextValue) => {
previousValue.push({
type: type.doc,
label: documentationItem.label,
path: nextValue.path,
});
return previousValue;
},
[]
),
template,
true
);
}
resolve();
})
.catch(err => {
reject(err);
});
});
}
/**
* Converts markdown documentation item, either a category or document
*
* @param {string} category
* @param {string} template
* @returns Promise
*/
function convertMarkdownDocumentation(category, template, isVersionDoc) {
return new Promise((resolve, reject) => {
category.forEach(documentationItem => {
if (documentationItem.type === type.category) {
const items = documentationItem.items.reduce(
(previousValue, nextDocumentationItem) => {
previousValue.push({
label: nextDocumentationItem.label,
path: nextDocumentationItem.path,
});
return previousValue;
},
[]
);
const catFile = {
type: type.category,
path: documentationItem.path,
html: templateResolver(template)({
htmlWebpackPlugin: {
options: {
content: templateResolver(
fs.readFileSync(categoryTemplate, "utf8")
)({
items,
label: documentationItem.label,
description: documentationItem.description,
baseUrl,
}),
toolbarTemplate: templateResolver(
fs.readFileSync(toolbarTemplate, "utf8")
)({
baseUrl,
}),
footerTemplate: templateResolver(
fs.readFileSync(footerTemplate, "utf8")
)(),
styleTemplate: fs.readFileSync(styleTemplate, "utf8"),
metaTemplate: templateResolver(
fs.readFileSync(metaTemplate, "utf8")
)({
baseUrl,
}),
sidebar: templateResolver(
fs.readFileSync(sidebarTemplate, "utf8")
)({
sidebar,
currentPath: documentationItem.path,
baseUrl,
}),
},
},
}),
};
fs.ensureDir(path.resolve(outDir, catFile.path))
.then(() => {
fs.writeFileSync(
path.resolve(outDir, catFile.path, "index.html"),
catFile.html
);
})
.finally(() => {
resolve();
})
.catch(err => {
reject(err);
});
writeToHTML(documentationItem.items, template, isVersionDoc);
} else if (documentationItem.type === type.doc) {
convertDocument(documentationItem, template, isVersionDoc).then(() => {
resolve();
});
} else {
reject("Unrecognizable type used in sidebar");
}
});
});
}
/**
* Write a document or category to an HTML file
*
* @param {array} category
* @param {string} template
* @returns Promise
*/
function writeToHTML(category, template, isVersionDoc) {
return new Promise((resolve, reject) => {
convertMarkdownDocumentation(category, template, isVersionDoc, {}).then(() => {
resolve();
});
});
}
/**
* Execute the readfile on the index.html which serves as the frontpage template and documentation templates
* then write to HTML all of the documentation as defined in the sidebar.json
*/
fs.readFile(path.resolve(__dirname, "src/index.html"), "utf8", (err, data) => {
if (err) {
throw err;
}
writeToHTML(sidebar.documentation, data, false);
});

17
website/build/gh-pages.js Normal file
Просмотреть файл

@ -0,0 +1,17 @@
/**
* This script moves the generated site from www to the root docs/ folder recognized by github pages
*/
import fs from "fs-extra";
import path from "path";
const __dirname = process.cwd();
fs.copy(path.resolve(__dirname, "www"), path.resolve(__dirname, "../docs"), function (
err
) {
if (err) {
return console.error(err);
}
console.log("Generated static files copied to docs folder for GitHub pages.");
});

2
website/docs/examples.md Normal file
Просмотреть файл

@ -0,0 +1,2 @@
# Examples
TBD

Просмотреть файл

@ -0,0 +1 @@
# Version 2.x

Просмотреть файл

@ -0,0 +1,2 @@
# Form
TBD

Просмотреть файл

@ -0,0 +1,2 @@
# Navigation
TBD

Просмотреть файл

@ -0,0 +1,2 @@
# Viewer
TBD

Просмотреть файл

@ -0,0 +1,3 @@
# Description
This folder contains the documentation for versions of the `@microsoft/fast-tooling-react` package.

Просмотреть файл

@ -0,0 +1 @@
# Version 0.x

Просмотреть файл

@ -0,0 +1,2 @@
# Color Picker
TBD

Просмотреть файл

@ -0,0 +1,2 @@
# CSS Box Model
TBD

Просмотреть файл

@ -0,0 +1,2 @@
# CSS Layout
TBD

Просмотреть файл

@ -0,0 +1,2 @@
# File
TBD

Просмотреть файл

@ -0,0 +1,2 @@
# HTML Render
TBD

Просмотреть файл

@ -0,0 +1,2 @@
# Units Text Field
TBD

Просмотреть файл

@ -0,0 +1,2 @@
# Create a Service
TBD

Просмотреть файл

@ -0,0 +1,2 @@
# Data Validation
TBD

Просмотреть файл

@ -0,0 +1,2 @@
# Monaco Editor
TBD

Просмотреть файл

@ -0,0 +1,2 @@
# Shortcuts
TBD

Просмотреть файл

@ -0,0 +1,2 @@
# Data Format
TBD

Просмотреть файл

@ -0,0 +1,7 @@
# Message System
FAST tooling components rely on including a secondary script which contains a [web worker](https://developer.mozilla.org/en-US/docs/Web/API/Worker) called the message system.
This worker performs all of the data manipulation and provides a navigational data structure based on data passed.
TBD

Просмотреть файл

@ -0,0 +1,2 @@
# Messages
TBD

Просмотреть файл

@ -0,0 +1,3 @@
# Description
This folder contains the documentation for versions of the `@microsoft/fast-tooling` package.

Просмотреть файл

@ -0,0 +1,3 @@
# Introduction
Welcome to FAST tooling, an ecosystem of packages built for the purpose of live updating JSON data.

158
website/docs/sidebar.js Normal file
Просмотреть файл

@ -0,0 +1,158 @@
import versions from "./versions.json";
const toolingPackageName = "@microsoft/fast-tooling";
const toolingReactPackageName = "@microsoft/fast-tooling-react";
/**
* The contents of the "documentation" property can either be a "doc" or "category".
*
* A "doc" must contain the following properties:
* {
* type: "doc", // identify this item as a document
* label: "Example" // the readable label used in the sidebar UI
* path: "path/to/example" // the path to the file the doc is referencing without the ".md"
* }
*
* A "category" must contain the following properties:
* {
* type: "category", // identify this item as a category
* label: "Example", // the readable label used in the sidebar UI
* path: "path/to/example", // the path to use as an index of items
* description: "" // a description that will show up as a paragraph on the category page
* items: [ // the list of items in this category
* {
* type: "doc", // nesting only goes one level deep, do not place a category type as a category item
* ...see above "doc" type
* }
* ]
* }
*/
export default {
documentation: [
{
type: "doc",
label: "Introduction",
path: "introduction",
},
{
type: "doc",
label: "Examples",
path: "examples",
},
{
type: "category",
label: "Message System",
description:
"A web worker that serves as the fundamental backbone to the FAST tooling project.",
path: "message-system",
items: [
{
type: "doc",
label: "Introduction",
path: `fast-tooling/${versions[toolingPackageName].versions[0]}/message-system/introduction`,
},
{
type: "doc",
label: "Messages",
path: `fast-tooling/${versions[toolingPackageName].versions[0]}/message-system/messages`,
},
{
type: "doc",
label: "Data Format",
path: `fast-tooling/${versions[toolingPackageName].versions[0]}/message-system/data-format`,
},
],
},
{
type: "category",
label: "React Components",
description:
"A set of React components that can be registered with the Message System.",
path: "react-components",
items: [
{
type: "doc",
label: "Form",
path: `fast-tooling-react/${versions[toolingReactPackageName].versions[0]}/components/form`,
},
{
type: "doc",
label: "Navigation",
path: `fast-tooling-react/${versions[toolingReactPackageName].versions[0]}/components/navigation`,
},
{
type: "doc",
label: "Viewer",
path: `fast-tooling-react/${versions[toolingReactPackageName].versions[0]}/components/viewer`,
},
],
},
{
type: "category",
label: "Web Components",
description:
"A set of FAST-based web components that can be registered with the Message System.",
path: "web-components",
items: [
{
type: "doc",
label: "Color Picker",
path: `fast-tooling/${versions[toolingPackageName].versions[0]}/components/color-picker`,
},
{
type: "doc",
label: "CSS Box Model",
path: `fast-tooling/${versions[toolingPackageName].versions[0]}/components/css-box-model`,
},
{
type: "doc",
label: "CSS Layout",
path: `fast-tooling/${versions[toolingPackageName].versions[0]}/components/css-layout`,
},
{
type: "doc",
label: "File",
path: `fast-tooling/${versions[toolingPackageName].versions[0]}/components/file`,
},
{
type: "doc",
label: "HTML Render",
path: `fast-tooling/${versions[toolingPackageName].versions[0]}/components/html-render`,
},
{
type: "doc",
label: "Units Text Field",
path: `fast-tooling/${versions[toolingPackageName].versions[0]}/components/units-text-field`,
},
],
},
{
type: "category",
label: "Message System Services",
description:
"A set of class-based services that can be registered with the Message System.",
path: "message-system-services",
items: [
{
type: "doc",
label: "Shortcuts",
path: `fast-tooling/${versions[toolingPackageName].versions[0]}/message-system-services/shortcuts`,
},
{
type: "doc",
label: "Monaco Editor",
path: `fast-tooling/${versions[toolingPackageName].versions[0]}/message-system-services/monaco-editor`,
},
{
type: "doc",
label: "Data Validation",
path: `fast-tooling/${versions[toolingPackageName].versions[0]}/message-system-services/data-validation`,
},
{
type: "doc",
label: "Create a Service",
path: `fast-tooling/${versions[toolingPackageName].versions[0]}/message-system-services/create-a-service`,
},
],
},
],
};

7
website/docs/templates/category/index.html поставляемый Normal file
Просмотреть файл

@ -0,0 +1,7 @@
<h1><%- label %></h1>
<p><%- description %></p>
<ul class="category">
<% _.forEach(items, function(item) { %>
<li><a href="<%- baseUrl %>/docs/<%- item.path %>"><%- item.label %></a></li>
<% }); %>
</ul>

48
website/docs/templates/sidebar/index.html поставляемый Normal file
Просмотреть файл

@ -0,0 +1,48 @@
<div class="sidebar">
<div class="mobile-control">
<span>FAST Tooling</span>
<button id="mobileClose" class="mobile-toggle">
<svg viewBox="0 0 15 15" width="21" height="21">
<g stroke="#ccd0d5" stroke-width="1.2">
<path d="M.75.75l13.5 13.5M14.25.75L.75 14.25"></path>
</g>
</svg>
</button>
</div>
<nav>
<ul>
<% _.forEach(sidebar.documentation, function(documentationItem) { %>
<li>
<a
class="<%- documentationItem.path === currentPath ? 'active' : '' %>"
href="<%- baseUrl %>/docs/<%- documentationItem.path %>"
>
<%- documentationItem.label %>
</a>
<% if (Array.isArray(documentationItem.items)) { %>
<ul>
<% _.forEach(documentationItem.items, function(categoryItem) { %>
<li>
<a
class="<%- categoryItem.path === currentPath ? 'active' : '' %>"
href="<%- baseUrl %>/docs/<%- categoryItem.path %>"
>
<%- categoryItem.label %>
</a>
</li>
<% }); %>
</ul>
<% } %>
</li>
<% }); %>
</ul>
</nav>
<script>
var mobileCloseButton = document.getElementById("mobileClose");
mobileCloseButton.addEventListener("mousedown", e => {
e.preventDefault();
document.body.classList.remove("active-mobile-sidebar");
});
</script>
</div>

25
website/docs/templates/version/index.html поставляемый Normal file
Просмотреть файл

@ -0,0 +1,25 @@
<table>
<caption>
package:
<code><%- versionInfo.package %></code>
</caption>
<thead>
<tr>
<th colspan="1">
version
</th>
</tr>
</thead>
<tbody>
<tr>
<td><em><%- versionInfo.docVersion %> - current</em></td>
</tr>
<% _.forEach(versionInfo.otherAvailableVersions, function(version) { %>
<tr>
<td>
<a href="<%- baseUrl %>/docs/<%- version.path %>"><%- version.label %></a>
</td>
</tr>
<% }); %>
</tbody>
</table>

Просмотреть файл

@ -0,0 +1,12 @@
{
"@microsoft/fast-tooling": {
"versions": [
"0.x"
]
},
"@microsoft/fast-tooling-react": {
"versions": [
"2.x"
]
}
}

4280
website/package-lock.json сгенерированный Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

26
website/package.json Normal file
Просмотреть файл

@ -0,0 +1,26 @@
{
"name": "website",
"version": "0.0.0",
"private": true,
"type": "module",
"scripts": {
"build:frontpage": "webpack",
"build:docs": "node --experimental-json-modules ./build/docs.js",
"build": "npm run build:frontpage && npm run build:docs",
"serve": "npm run build && node ./server.js",
"build:docs:gh-pages": "node --experimental-json-modules ./build/docs.js gh-pages",
"build:frontpage:gh-pages": "webpack --env=gh-pages",
"build:gh-pages": "npm run build:frontpage:gh-pages && npm run build:docs:gh-pages && node ./build/gh-pages.js"
},
"devDependencies": {
"express": "^4.17.3",
"fs-extra": "^10.0.1",
"html-webpack-plugin": "^5.5.0",
"lodash-es": "^4.17.21",
"marked": "^4.0.12",
"ts-loader": "^9.2.8",
"typescript": "^4.6.2",
"webpack": "^5.70.0",
"webpack-cli": "^4.9.2"
}
}

15
website/server.js Normal file
Просмотреть файл

@ -0,0 +1,15 @@
import express from "express";
import path from "path";
import http from "http";
const __dirname = process.cwd();
const app = express();
const outDir = path.join(__dirname, "www");
/**
* This express file is only for development purposes, the
* build should be statically served from GitHub pages
*/
app.use("/", express.static(outDir))
http.createServer(app).listen(3000);

28
website/src/index.html Normal file
Просмотреть файл

@ -0,0 +1,28 @@
<!DOCTYPE html>
<html lang="en">
<head>
<%= htmlWebpackPlugin.options.metaTemplate %> <%=
htmlWebpackPlugin.options.styleTemplate %>
</head>
<body class="<%= htmlWebpackPlugin.options.isFrontpage ? '' : 'docs' %>">
<div class="mobile-overlay"></div>
<div>
<%= htmlWebpackPlugin.options.toolbarTemplate %>
<main>
<%= htmlWebpackPlugin.options.isFrontpage ? "" :
htmlWebpackPlugin.options.sidebar %>
<div class="content">
<%= htmlWebpackPlugin.options.versionInfo ?
htmlWebpackPlugin.options.versionInfo : "" %> <%=
htmlWebpackPlugin.options.content %>
</div>
</main>
</div>
<%= htmlWebpackPlugin.options.footerTemplate %>
</body>
</html>

0
website/src/index.ts Normal file
Просмотреть файл

Просмотреть файл

@ -0,0 +1,43 @@
<div class="frontpage">
<h1>FAST Tooling</h1>
<p>
This is the FAST Tooling project, containing a set of packages that can be
combined to create complex workflows for web applications. The goal of these
workflows is to allow users to create and modify their own web based experiences,
from individual web components to completed web sites.
</p>
<div class="card-container">
<div class="card">
<h2>Dive in</h2>
<p>
Get started with our
<a href="<%- baseUrl %>/docs/introduction">introduction</a>
which will explain the fundamentals of how the tooling ecosystem works and
what you need to get going.
</p>
</div>
<div class="card">
<h2>Browse our examples</h2>
<p>
There are a number of components and services available from our packages
that can be registered with the message system. To get an overview of how
these can be combined, check out our
<a href="<%- baseUrl %>/docs/examples">examples</a>
.
</p>
</div>
<div class="card">
<h2>Create a service</h2>
<p>
Want to interact with the message system with your own service? To find
out more read the page on
<a
href="<%- baseUrl %>/docs/fast-tooling/0.x/message-system-services/create-a-service"
>
creating a service
</a>
.
</p>
</div>
</div>
</div>

Просмотреть файл

@ -0,0 +1,176 @@
<footer>
<div class="links">
<div>
<h3>Community</h3>
<ul>
<li>
<a
href="https://discord.gg/FcSNfg4"
target="_blank"
rel="noopener noreferrer"
>
<span>
Discord
<svg
width="13.5"
height="13.5"
aria-hidden="true"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"
></path>
</svg>
</span>
</a>
</li>
</ul>
</div>
<div>
<h3>Social</h3>
<ul>
<li>
<a
href="https://github.com/microsoft/fast-tooling"
target="_blank"
rel="noopener noreferrer"
>
<span>
GitHub
<svg
width="13.5"
height="13.5"
aria-hidden="true"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"
></path>
</svg>
</span>
</a>
</li>
<li>
<a
href="https://twitter.com/FAST_UI"
target="_blank"
rel="noopener noreferrer"
>
<span>
Twitter
<svg
width="13.5"
height="13.5"
aria-hidden="true"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"
></path>
</svg>
</span>
</a>
</li>
</ul>
</div>
<div>
<h3>&nbsp;</h3>
<ul>
<li>
<a
href="https://github.com/microsoft/fast-tooling/blob/main/LICENSE"
target="_blank"
rel="noopener noreferrer"
>
<span>
License
<svg
width="13.5"
height="13.5"
aria-hidden="true"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"
></path>
</svg>
</span>
</a>
</li>
<li>
<a
href="https://go.microsoft.com/fwlink/?LinkId=521839"
target="_blank"
rel="noopener noreferrer"
>
<span>
Privacy &amp; cookies
<svg
width="13.5"
height="13.5"
aria-hidden="true"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"
></path>
</svg>
</span>
</a>
</li>
<li>
<a
href="https://go.microsoft.com/fwlink/?LinkID=206977"
target="_blank"
rel="noopener noreferrer"
>
<span>
Terms of use
<svg
width="13.5"
height="13.5"
aria-hidden="true"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"
></path>
</svg>
</span>
</a>
</li>
<li>
<a
href="https://www.microsoft.com/trademarks"
target="_blank"
rel="noopener noreferrer"
>
<span>
Trademarks
<svg
width="13.5"
height="13.5"
aria-hidden="true"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"
></path>
</svg>
</span>
</a>
</li>
</ul>
</div>
</div>
<div class="copyright">
<div>© Microsoft <%- new Date().getFullYear() %></div>
</div>
</footer>

Просмотреть файл

@ -0,0 +1,25 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>FAST Tooling</title>
<meta
name="description"
content="A system of development tools, and utilities used à la carte or as a suite to build enterprise-grade websites and applications."
/>
<meta name="author" content="Microsoft" />
<meta
property="og:title"
content="A system of development tools, and utilities used à la carte or as a suite to build enterprise-grade websites and applications."
/>
<meta property="og:type" content="website" />
<meta property="og:url" content="https://www.example.com/" />
<meta
property="og:description"
content="A system of development tools, and utilities used à la carte or as a suite to build enterprise-grade websites and applications."
/>
<meta property="og:image" content="image.png" />
<link rel="icon" href="<%- baseUrl %>/favicon.ico" />
<link rel="icon" href="<%- baseUrl %>/favicon.svg" type="image/svg+xml" />
<link rel="apple-touch-icon" href="<%- baseUrl %>/apple-touch-icon.png" />

Просмотреть файл

@ -0,0 +1,333 @@
<style>
body,
html {
margin: 0;
padding: 0;
}
body {
--link-color: #ebedf0;
--accent-link-color: #fb356d;
--font-color: #f5f6f7;
--font-family: system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell,
Noto Sans, sans-serif, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial,
sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
--background-color-layer-1: #18191a;
--background-color-layer-2: #242526;
--background-color-layer-3: hsla(0, 0%, 100%, 0.05);
--footer-background-color: #303846;
--footer-color: #ebefd0;
--footer-height: 220px;
--spacing-vertical: 20px;
--table-background: transparent;
--table-border-width: 1px;
--table-border-color: #606770;
--table-head-background: inherit;
--table-head-color: inherit;
--table-head-font-weight: 700;
--table-cell-padding: 10px;
--sidebar-border-color: #606770;
--sidebar-width: 300px;
--sidebar-link-active-background-color: var(--background-color-layer-3);
--sidebar-background-color: var(--background-color-layer-2);
--toolbar-background-color: var(--background-color-layer-2);
--toolbar-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.1);
--toolbar-height: 60px;
--category-border-color: #444950;
--category-background-color: var(--background-color-layer-2);
--category-border-radius: 10px;
--table-caption-background-color: var(--background-color-layer-3);
display: flex;
flex-direction: column;
justify-content: space-between;
min-height: 100vh;
background: var(--background-color-layer-1);
color: var(--font-color);
font-family: var(--font-family);
}
.toolbar {
position: sticky;
top: 0;
}
.toolbar .section {
display: flex;
padding: 0 15px;
}
header nav {
display: flex;
height: var(--toolbar-height);
justify-content: space-between;
background-color: var(--toolbar-background-color);
box-shadow: var(--toolbar-shadow);
}
header nav ul {
display: flex;
padding: 15px 0;
}
header nav li {
padding: 0 10px;
}
.icon {
height: 20px;
width: 18px;
fill: var(--link-color);
}
a:hover .icon {
fill: var(--accent-link-color);
}
.sidebar {
width: var(--sidebar-width);
min-width: var(--sidebar-width);
border-right: 1px solid var(--sidebar-border-color);
height: calc(100vh - var(--toolbar-height) - var(--footer-height) - 30px);
overflow: auto;
}
.sidebar nav {
margin-inline-start: -20px;
}
.sidebar nav > ul {
margin: 20px 0;
}
.sidebar a {
display: flex;
line-height: 1.25;
flex: 1;
padding: 10px 15px;
border-radius: 5px;
color: var(--link-color);
}
.sidebar .active {
background: var(--sidebar-link-active-background-color);
}
.category {
margin: var(--spacing-vertical) 0;
padding: 0;
display: flex;
row-gap: 15px;
column-gap: 15px;
flex-wrap: wrap;
}
.category li {
border: 1px solid var(--category-border-color);
background: var(--category-background-color);
box-shadow: 0 1.5px 3px 0 rgb(0 0 0 / 15%);
padding: 20px;
border-radius: var(--category-border-radius);
width: 200px;
}
.category li a {
color: var(--link-color);
}
.category a,
.toolbar a,
.sidebar a,
footer a {
display: flex;
align-items: center;
column-gap: 5px;
}
a {
color: var(--link-color);
text-decoration: none;
}
a:hover {
color: var(--accent-link-color);
}
main {
display: flex;
margin: 0 25px 0 5px;
}
main > div {
margin-inline-start: 25px;
}
main div a {
color: var(--accent-link-color);
}
main ul {
padding-inline-start: 20px;
padding-inline-end: 20px;
}
.content {
width: 100%;
}
.frontpage {
margin: var(--spacing-vertical);
}
.card-container {
display: flex;
flex-wrap: wrap;
column-gap: 15px;
row-gap: 15px;
justify-content: center;
margin: 50px 0;
}
.card {
background: var(--background-color-layer-3);
border-radius: 5px;
padding: 0 20px;
width: 300px;
}
.mobile-overlay {
display: none;
}
.mobile-control {
display: none;
}
.mobile-toggle {
background: none;
border: none;
color: inherit;
cursor: pointer;
font-family: inherit;
padding: 0;
display: none;
}
ul {
padding: 0;
margin: 0;
list-style: none;
}
li {
line-height: 26px;
}
h1 {
margin: var(--spacing-vertical) 0;
}
footer {
display: flex;
flex-direction: column;
justify-content: space-between;
row-gap: 15px;
padding: 15px;
min-height: var(--footer-height);
background-color: var(--footer-background-color);
color: var(--footer-color);
}
footer .links {
display: flex;
justify-content: space-around;
column-gap: 15px;
}
footer .links svg {
margin-inline-start: 5px;
position: relative;
top: 1px;
}
footer .copyright {
text-align: center;
}
table {
border-collapse: collapse;
display: block;
margin: var(--spacing-vertical) 0;
overflow: auto;
box-sizing: border-box;
}
table caption {
display: inline-block;
margin-block-end: 15px;
background: var(--table-caption-background-color);
border-radius: 4px;
padding: 5px 10px;
}
table thead tr {
border-bottom: 2px solid var(--table-border-color);
}
table tr {
background-color: var(--table-background);
border-top: var(--table-border-width) solid var(--table-border-color);
}
table th {
background-color: var(--table-head-background);
color: var(--table-head-color);
font-weight: var(--table-head-font-weight);
}
table td,
table th {
border: var(--table-border-width) solid var(--table-border-color);
padding: var(--table-cell-padding);
}
@media (max-width: 996px) {
.mobile-control {
display: flex;
padding: 15px;
justify-content: space-between;
}
.docs .mobile-toggle {
display: block;
}
.sidebar {
margin-inline-start: calc((-1 * var(--sidebar-width)) - 6px);
}
.active-mobile-sidebar .sidebar {
margin-inline-start: -5px;
padding-inline-start: 5px;
position: absolute;
top: 0;
background: var(--sidebar-background-color);
height: 100vh;
z-index: 1;
}
.active-mobile-sidebar .mobile-overlay {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: black;
opacity: 0.8;
z-index: 1;
}
footer .links {
flex-direction: column;
}
}
</style>

Просмотреть файл

@ -0,0 +1,55 @@
<header class="toolbar">
<nav>
<div class="section">
<button id="mobileOpen" class="mobile-toggle">
<svg width="30" height="30" viewBox="0 0 30 30" aria-hidden="true">
<path
stroke="currentColor"
stroke-linecap="round"
stroke-miterlimit="10"
stroke-width="2"
d="M4 7h22M4 15h22M4 23h22"
></path>
</svg>
</button>
<ul>
<li>
<a href="<%- baseUrl %>/">
FAST Tooling
</a>
</li>
<li>
<a href="<%- baseUrl %>/docs/introduction">
Docs
</a>
</li>
</ul>
</div>
<div class="section">
<ul>
<li>
<a href="https://github.com/microsoft/fast-tooling" target="_blank">
<span>GitHub</span>
<svg
xmlns="http://www.w3.org/2000/svg"
class="icon icon-github"
viewBox="0 0 19 20"
>
<path
d="M6.71154 17.0776C2.09615 18.4906 2.09615 14.7226 0.25 14.2517L6.71154 17.0776ZM13.1731 19.9036V16.2581C13.2077 15.8089 13.1482 15.3574 12.9986 14.9335C12.849 14.5096 12.6127 14.123 12.3054 13.7995C15.2038 13.4698 18.25 12.3489 18.25 7.20563C18.2498 5.89046 17.754 4.62572 16.8654 3.67319C17.2862 2.52257 17.2564 1.25074 16.7823 0.121918C16.7823 0.121918 15.6931 -0.207776 13.1731 1.51605C11.0574 0.930913 8.82722 0.930913 6.71154 1.51605C4.19154 -0.207776 3.10231 0.121918 3.10231 0.121918C2.62819 1.25074 2.59844 2.52257 3.01923 3.67319C2.12396 4.63279 1.62771 5.90895 1.63462 7.23389C1.63462 12.3394 4.68077 13.4604 7.57923 13.8278C7.27554 14.148 7.04132 14.5299 6.89182 14.9486C6.74233 15.3674 6.6809 15.8135 6.71154 16.2581V19.9036"
></path>
</svg>
</a>
</li>
</ul>
</div>
</nav>
<script>
var mobileOpenButton = document.getElementById("mobileOpen");
mobileOpenButton.addEventListener("mousedown", e => {
e.preventDefault();
document.body.classList.add("active-mobile-sidebar");
});
</script>
</header>

17
website/tsconfig.json Normal file
Просмотреть файл

@ -0,0 +1,17 @@
{
"extends": "../tsconfig.json",
"include": [
"src/**/*"
],
"compilerOptions": {
"baseUrl": "./",
"declaration": false,
"outDir": "dist/esm",
"resolveJsonModule": true,
"allowJs": true
},
"exclude": [
"app",
"node_modules"
]
}

68
website/webpack.config.js Normal file
Просмотреть файл

@ -0,0 +1,68 @@
import path from "path";
import HtmlWebpackPlugin from "html-webpack-plugin";
import fs from "fs-extra";
import { template as templateResolver } from "lodash-es";
import { ghPagesBaseUrl } from "./build/constants.js";
const __dirname = process.cwd();
const baseUrl = process.env.npm_lifecycle_event.includes("gh-pages")
? ghPagesBaseUrl
: "";
const appDir = path.resolve(__dirname, "./src");
const outDir = path.resolve(__dirname, "./www");
const frontpageContent = path.resolve(appDir, "templates/content.html");
const toolbarTemplate = path.resolve(appDir, "templates/toolbar/index.html");
const footerTemplate = path.resolve(appDir, "./templates/footer/index.html");
const styleTemplate = path.resolve(appDir, "./templates/style/index.html");
const metaTemplate = path.resolve(appDir, "./templates/meta/index.html");
export default {
entry: {
app: path.resolve(appDir, "index.ts"),
},
output: {
path: outDir,
publicPath: "/",
filename: "[name].js",
clean: true,
},
mode: "production",
module: {
rules: [
{
test: /.ts$/,
use: [
{
loader: "ts-loader",
options: {
compilerOptions: {
declaration: false,
},
},
},
],
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html",
inject: true,
content: templateResolver(fs.readFileSync(frontpageContent, "utf8"))({
baseUrl,
}),
toolbarTemplate: templateResolver(fs.readFileSync(toolbarTemplate, "utf8"))({
baseUrl,
}),
footerTemplate: templateResolver(fs.readFileSync(footerTemplate, "utf8"))(),
styleTemplate: fs.readFileSync(styleTemplate, "utf8"),
metaTemplate: templateResolver(fs.readFileSync(metaTemplate, "utf8"))({
baseUrl,
}),
isFrontpage: true,
}),
],
resolve: {
extensions: [".js", ".ts", ".json"],
},
};