[Designer] Implement Designer as PWA (#7473)
* In progess: Designer as PWA update * Update to PWA services for designer * Refactor to use workbox for serviceworker * Disable header in css and update icon * Rename config file and update manifest * Minor updates to PWA * Minor formatting fixes * Update source/nodejs/adaptivecards-site/themes/adaptivecards/layout/designer.ejs Co-authored-by: Aaron Gustafson <aaron@easy-designs.net> * Update package.json scripts * Minify service worker * Update url references for pipeline * Dynamic manifest file * Update designer.ejs Remove debug description * Add method to service-worker and add comments * Use local workbox files * Update workbox path * Revert 'Dynamic manifest file' * Update manifest file paths * Move workbox ingestion to come in through hexo generator Co-authored-by: Aaron Gustafson <aaron@easy-designs.net> Co-authored-by: Paul Campbell <paulcam@microsoft.com>
This commit is contained in:
Родитель
1141a99ca8
Коммит
25efe9d138
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -4,12 +4,13 @@
|
|||
"private": true,
|
||||
"scripts": {
|
||||
"clean": "hexo clean",
|
||||
"build": "hexo generate",
|
||||
"build": "hexo generate && npm run generate-sw",
|
||||
"release-deps": "npx lerna run --scope @microsoft/adaptivecards-site --include-dependencies release --stream",
|
||||
"generate-md-ac": "node node_modules/marked-schema/bin/marked-schema ../../../schemas/adaptive-card.json ./schema-explorer-toc.yml -r AdaptiveCard",
|
||||
"generate-md-hc": "node node_modules/marked-schema/bin/marked-schema ../../../schemas/host-config.json ./schema-hostconfig-toc.yml -r AdaptiveCardConfig",
|
||||
"release": "hexo clean && hexo generate",
|
||||
"start": "hexo server"
|
||||
"release": "hexo clean && hexo generate && npm run generate-sw",
|
||||
"start": "hexo server",
|
||||
"generate-sw": "npx workbox-cli injectManifest workbox-config.json"
|
||||
},
|
||||
"hexo": {
|
||||
"version": "5.4.0"
|
||||
|
@ -49,6 +50,7 @@
|
|||
"monaco-editor": "^0.29.1",
|
||||
"request": "^2.88.2",
|
||||
"request-promise": "^4.2.5",
|
||||
"workbox-cli": "^6.5.3",
|
||||
"yaml-front-matter": "^4.1.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
// Used pwa-builder as reference: https://github.com/pwa-builder/pwabuilder-serviceworkers/blob/master/serviceWorker5/pwabuilder-sw.js
|
||||
importScripts("node_modules/workbox/workbox-sw.js");
|
||||
|
||||
workbox.setConfig({
|
||||
modulePathPrefix: "node_modules/workbox/"
|
||||
});
|
||||
|
||||
// Precache all files from workbox-config
|
||||
workbox.precaching.precacheAndRoute(self.__WB_MANIFEST);
|
||||
|
||||
const HTML_CACHE = "html";
|
||||
const JS_CACHE = "javascript";
|
||||
const STYLE_CACHE = "stylesheets";
|
||||
const IMAGE_CACHE = "images";
|
||||
const FONT_CACHE = "fonts";
|
||||
const DEFAULT_CACHE = "default";
|
||||
|
||||
// Need separeate caching for our cross origin styling references
|
||||
workbox.routing.registerRoute(
|
||||
({ url }) => {
|
||||
return (
|
||||
url.href ===
|
||||
"https://www.microsoft.com/onerfstatics/marketingsites-wcus-prod/west-european/shell/_scrf/css/themes=default.device=uplevel_web_pc/59-469920/ad-9005a4/bd-292223/26-13ca9e/b7-1464e7/8e-a868c0/58-faa810/34-4fda9f?ver=2.0" ||
|
||||
url.href ===
|
||||
"https://statics-marketingsites-wcus-ms-com.akamaized.net/statics/override.css?c=7"
|
||||
);
|
||||
},
|
||||
new workbox.strategies.CacheFirst({
|
||||
plugins: [
|
||||
new workbox.cacheableResponse.CacheableResponsePlugin({
|
||||
statuses: [0, 200]
|
||||
})
|
||||
]
|
||||
})
|
||||
);
|
||||
|
||||
// TODO: could register routes with regex if we want to be more precise with caching
|
||||
workbox.routing.registerRoute(
|
||||
({ event }) => {
|
||||
return event.request.destination === "document";
|
||||
},
|
||||
new workbox.strategies.NetworkFirst({
|
||||
cacheName: HTML_CACHE,
|
||||
plugins: [
|
||||
new workbox.expiration.ExpirationPlugin({
|
||||
maxEntries: 10
|
||||
})
|
||||
]
|
||||
})
|
||||
);
|
||||
|
||||
function registerStaleWhileRevalidate(destinationType, cache, entries) {
|
||||
workbox.routing.registerRoute(
|
||||
({ event }) => {
|
||||
return event.request.destination === destinationType;
|
||||
},
|
||||
new workbox.strategies.StaleWhileRevalidate({
|
||||
cacheName: cache,
|
||||
plugins: [
|
||||
new workbox.expiration.ExpirationPlugin({
|
||||
maxEntries: entries
|
||||
})
|
||||
]
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
registerStaleWhileRevalidate("script", JS_CACHE, 15);
|
||||
registerStaleWhileRevalidate("style", STYLE_CACHE, 15);
|
||||
registerStaleWhileRevalidate("image", IMAGE_CACHE, 15);
|
||||
registerStaleWhileRevalidate("font", FONT_CACHE, 15);
|
||||
|
||||
// This route mostly caches payloads
|
||||
// We allow for a high cache so the sample cards and data are stored
|
||||
registerStaleWhileRevalidate("", DEFAULT_CACHE, 100);
|
|
@ -23,6 +23,10 @@
|
|||
<link rel="alternate" href="<%- url_for(config.feed.path) %>" title="<%= config.title %>" type="application/atom+xml">
|
||||
<link rel="icon" href="<%- url_for('content/favicon.ico') %>">
|
||||
|
||||
<% if(is_current("designer")) { %>
|
||||
<link rel="manifest" href="<%- url_for('manifest.json') %>">
|
||||
<% } %>
|
||||
|
||||
<% if(is_post()) { %>
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta name="twitter:title" content="Adaptive Cards | <%- page.title %>">
|
||||
|
@ -47,6 +51,7 @@
|
|||
|
||||
|
||||
<% /* from UHF MSDocsHeader-AdaptiveCards */ %>
|
||||
|
||||
<link rel="stylesheet" href="https://www.microsoft.com/onerfstatics/marketingsites-wcus-prod/west-european/shell/_scrf/css/themes=default.device=uplevel_web_pc/59-469920/ad-9005a4/bd-292223/26-13ca9e/b7-1464e7/8e-a868c0/58-faa810/34-4fda9f?ver=2.0" type="text/css" media="all" />
|
||||
<link rel='stylesheet' href='https://statics-marketingsites-wcus-ms-com.akamaized.net/statics/override.css?c=7' type='text/css' />
|
||||
<script src="https://www.microsoft.com/onerfstatics/marketingsites-wcus-prod/shell/_scrf/js/themes=default/54-af9f9f/c0-247156/de-099401/e1-a50eee/e7-954872/d8-97d509/f0-251fe2/46-be1318/77-04a268/11-240c7b/63-077520/a4-34de62/1b-c96630/db-bc0148/dc-7e9864/78-4c7d22/39-97e6ff/16-4c1a9d/cd-23d3b0/6d-1e7ed0/b7-cadaa7/ca-40b7b0/4e-ee3a55/3e-f5c39b/c3-6454d7/f9-7592d3/92-10345d/79-499886/7e-cda2d3/62-95a6e7/93-283c2d/e0-3c9860/91-97a04f/1f-100dea/33-abe4df/f2-fae105?ver=2.0&iife=1"></script>
|
||||
|
|
|
@ -45,8 +45,27 @@
|
|||
.acd-icon-scopeTemplate::before {
|
||||
content: "\F2B0";
|
||||
}
|
||||
|
||||
@media all and (display-mode: standalone) {
|
||||
.header-holder {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
// Register the service worker for PWA
|
||||
if ('serviceWorker' in navigator) {
|
||||
window.addEventListener('load', () => {
|
||||
navigator.serviceWorker.register('<%- config.root %>service-worker.js', {scope: '<%- config.root %>designer/'}).then(registration => {
|
||||
console.log('SW registered: ', registration);
|
||||
}).catch(registrationError => {
|
||||
console.log('SW registration failed: ', registrationError);
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
|
|
|
@ -12,129 +12,159 @@ var md5 = require("md5");
|
|||
// These are the flat asset files that will be copied into the output folder
|
||||
// and available to reference in HTML templates
|
||||
var simpleAssets = [
|
||||
"node_modules/adaptivecards/dist/*.*",
|
||||
"node_modules/adaptive-expressions/lib/*.*",
|
||||
"node_modules/adaptivecards-designer/dist/*.*",
|
||||
"node_modules/adaptivecards-templating/dist/*.*",
|
||||
"node_modules/@fortawesome/fontawesome-free/css/all.min.css",
|
||||
"node_modules/@fortawesome/fontawesome-free/webfonts/*.*",
|
||||
"node_modules/highlightjs/highlight.pack.min.js",
|
||||
"node_modules/highlightjs/styles/default.css",
|
||||
"node_modules/jquery/dist/jquery.min.js",
|
||||
"node_modules/markdown-it/dist/markdown-it.min.js"
|
||||
"node_modules/adaptivecards/dist/*.*",
|
||||
"node_modules/adaptive-expressions/lib/*.*",
|
||||
"node_modules/adaptivecards-designer/dist/*.*",
|
||||
"node_modules/adaptivecards-templating/dist/*.*",
|
||||
"node_modules/@fortawesome/fontawesome-free/css/all.min.css",
|
||||
"node_modules/@fortawesome/fontawesome-free/webfonts/*.*",
|
||||
"node_modules/highlightjs/highlight.pack.min.js",
|
||||
"node_modules/highlightjs/styles/default.css",
|
||||
"node_modules/jquery/dist/jquery.min.js",
|
||||
"node_modules/markdown-it/dist/markdown-it.min.js"
|
||||
];
|
||||
|
||||
// These are the other asset files that need to be copied into a specific location
|
||||
// the dest param describes the dir/filename used in the output destination
|
||||
var customAssets = [
|
||||
{
|
||||
// Sample payloads
|
||||
path: "../../../samples/v1.*/**/*.json",
|
||||
dest: function (p) { return "payloads/" + path.basename(p); }
|
||||
},
|
||||
{
|
||||
// Sample template payloads
|
||||
path: "../../../samples/Templates/**/*.json",
|
||||
dest: function (p) { return "payloads/" + path.basename(p); }
|
||||
},
|
||||
{
|
||||
// Unversioned JSON schema URL, set to the 1.3 (current) version as versioned schema paths are not in use.
|
||||
// May be deprecated in the future in favor of versioned schema paths.
|
||||
path: "../../../schemas/1.5.0/adaptive-card.json",
|
||||
dest: function (p) { return "schemas/adaptive-card.json"; }
|
||||
},
|
||||
{
|
||||
path: "../../../schemas/*/adaptive-card.json",
|
||||
dest: function (p) {
|
||||
// Keep the last 2 path portions... 1.2.0/adaptive-card.json, and put it in the schemas folder
|
||||
return "schemas/" + p.split("/").slice(-2).join("/");
|
||||
}
|
||||
},
|
||||
{
|
||||
// CSS used for samples on the site
|
||||
path: "node_modules/adaptivecards-designer/dist/containers/outlook-container.css",
|
||||
dest: function (p) { return "css/outlook.css"; }
|
||||
},
|
||||
{
|
||||
// designer module (hashing not working for CSS files; the designer expects certain filenames)
|
||||
path: "node_modules/adaptivecards-designer/dist/containers/*.*",
|
||||
dest: function (p) { return p; },
|
||||
noHash: true
|
||||
},
|
||||
{
|
||||
// designer module (hashing not working for CSS files; the designer expects certain filenames)
|
||||
path: "node_modules/adaptivecards-designer/dist/adaptivecards-designer.css",
|
||||
dest: function (p) { return p; },
|
||||
noHash: true
|
||||
},
|
||||
{
|
||||
// monaco-editor module
|
||||
path: "node_modules/monaco-editor/min/vs/**/*.*",
|
||||
dest: function (p) { return p; },
|
||||
noHash: true
|
||||
},
|
||||
{
|
||||
// monaco-editor module maps, for science
|
||||
path: "node_modules/monaco-editor/min-maps/vs/**/*.*",
|
||||
dest: function (p) { return p; },
|
||||
noHash: true
|
||||
},
|
||||
{
|
||||
// site CSS
|
||||
path: "themes/adaptivecards/source/css/*.css",
|
||||
dest: function (p) { return "css/" + path.basename(p) }
|
||||
},
|
||||
{
|
||||
// site JS
|
||||
path: "themes/adaptivecards/source/js/*.js",
|
||||
dest: function (p) { return "js/" + path.basename(p) }
|
||||
}
|
||||
{
|
||||
// Sample payloads
|
||||
path: "../../../samples/v1.*/**/*.json",
|
||||
dest: function (p) {
|
||||
return "payloads/" + path.basename(p);
|
||||
}
|
||||
},
|
||||
{
|
||||
// Sample template payloads
|
||||
path: "../../../samples/Templates/**/*.json",
|
||||
dest: function (p) {
|
||||
return "payloads/" + path.basename(p);
|
||||
}
|
||||
},
|
||||
{
|
||||
// Unversioned JSON schema URL, set to the 1.3 (current) version as versioned schema paths are not in use.
|
||||
// May be deprecated in the future in favor of versioned schema paths.
|
||||
path: "../../../schemas/1.5.0/adaptive-card.json",
|
||||
dest: function (p) {
|
||||
return "schemas/adaptive-card.json";
|
||||
}
|
||||
},
|
||||
{
|
||||
path: "../../../schemas/*/adaptive-card.json",
|
||||
dest: function (p) {
|
||||
// Keep the last 2 path portions... 1.2.0/adaptive-card.json, and put it in the schemas folder
|
||||
return "schemas/" + p.split("/").slice(-2).join("/");
|
||||
}
|
||||
},
|
||||
{
|
||||
// CSS used for samples on the site
|
||||
path: "node_modules/adaptivecards-designer/dist/containers/outlook-container.css",
|
||||
dest: function (p) {
|
||||
return "css/outlook.css";
|
||||
}
|
||||
},
|
||||
{
|
||||
// designer module (hashing not working for CSS files; the designer expects certain filenames)
|
||||
path: "node_modules/adaptivecards-designer/dist/containers/*.*",
|
||||
dest: function (p) {
|
||||
return p;
|
||||
},
|
||||
noHash: true
|
||||
},
|
||||
{
|
||||
// designer module (hashing not working for CSS files; the designer expects certain filenames)
|
||||
path: "node_modules/adaptivecards-designer/dist/adaptivecards-designer.css",
|
||||
dest: function (p) {
|
||||
return p;
|
||||
},
|
||||
noHash: true
|
||||
},
|
||||
{
|
||||
// monaco-editor module
|
||||
path: "node_modules/monaco-editor/min/vs/**/*.*",
|
||||
dest: function (p) {
|
||||
return p;
|
||||
},
|
||||
noHash: true
|
||||
},
|
||||
{
|
||||
// monaco-editor module maps, for science
|
||||
path: "node_modules/monaco-editor/min-maps/vs/**/*.*",
|
||||
dest: function (p) {
|
||||
return p;
|
||||
},
|
||||
noHash: true
|
||||
},
|
||||
{
|
||||
// site CSS
|
||||
path: "themes/adaptivecards/source/css/*.css",
|
||||
dest: function (p) {
|
||||
return "css/" + path.basename(p);
|
||||
}
|
||||
},
|
||||
{
|
||||
// site JS
|
||||
path: "themes/adaptivecards/source/js/*.js",
|
||||
dest: function (p) {
|
||||
return "js/" + path.basename(p);
|
||||
}
|
||||
},
|
||||
{
|
||||
path: "node_modules/workbox-!(cli|build)/build/*",
|
||||
dest: function (p) {
|
||||
return "node_modules/workbox/" + path.basename(p);
|
||||
},
|
||||
noHash: true
|
||||
}
|
||||
];
|
||||
|
||||
hexo.extend.generator.register("generator-adaptiveassets", function (locals) {
|
||||
let allAssets = [];
|
||||
let hashExtensions = [".css", ".js"];
|
||||
let hashedAssets = [];
|
||||
|
||||
let allAssets = [];
|
||||
let hashExtensions = [".css", ".js"];
|
||||
let hashedAssets = [];
|
||||
simpleAssets.forEach(function (a) {
|
||||
customAssets.push({
|
||||
path: a,
|
||||
dest: function (p) {
|
||||
return p;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
simpleAssets.forEach(function (a) {
|
||||
customAssets.push({
|
||||
path: a,
|
||||
dest: function (p) { return p; }
|
||||
});
|
||||
});
|
||||
customAssets.forEach(function (asset) {
|
||||
var g = glob.sync(asset.path, { nocase: false }).map(function (sourcePath) {
|
||||
let destPath = asset.dest(sourcePath);
|
||||
|
||||
customAssets.forEach(function (asset) {
|
||||
var g = glob.sync(asset.path, { nocase: false }).map(function (sourcePath) {
|
||||
if (!asset.noHash && hashExtensions.includes(path.extname(destPath))) {
|
||||
// For cache-busting append the md5 hash of our script and CSS content
|
||||
// EXAMPLE: adaptivecards.js => adaptivecards.c66a8322.js
|
||||
let originalDestPath = destPath;
|
||||
let hash = md5(fs.readFileSync(sourcePath)).substring(0, 6);
|
||||
let hashedFilename =
|
||||
path.basename(destPath, path.extname(destPath)) + "." + hash + path.extname(destPath);
|
||||
|
||||
let destPath = asset.dest(sourcePath);
|
||||
destPath = path.dirname(destPath) + "/" + hashedFilename;
|
||||
hashedAssets.push({
|
||||
originalPath: originalDestPath,
|
||||
hashedPath: destPath
|
||||
});
|
||||
}
|
||||
|
||||
if (!asset.noHash && hashExtensions.includes(path.extname(destPath))) {
|
||||
// For cache-busting append the md5 hash of our script and CSS content
|
||||
// EXAMPLE: adaptivecards.js => adaptivecards.c66a8322.js
|
||||
let originalDestPath = destPath;
|
||||
let hash = md5(fs.readFileSync(sourcePath)).substring(0, 6);
|
||||
let hashedFilename = path.basename(destPath, path.extname(destPath)) + "." + hash + path.extname(destPath);
|
||||
return {
|
||||
path: destPath,
|
||||
data: function () {
|
||||
return fs.createReadStream(sourcePath);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
destPath = path.dirname(destPath) + "/" + hashedFilename;
|
||||
hashedAssets.push({
|
||||
originalPath: originalDestPath,
|
||||
hashedPath: destPath
|
||||
});
|
||||
}
|
||||
g.forEach(function (item) {
|
||||
allAssets.push(item);
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
path: destPath,
|
||||
data: function () {
|
||||
return fs.createReadStream(sourcePath);
|
||||
}
|
||||
}
|
||||
});
|
||||
hexo.locals.set("hashedAssets", () => hashedAssets);
|
||||
|
||||
g.forEach(function (item) { allAssets.push(item); });
|
||||
});
|
||||
|
||||
hexo.locals.set("hashedAssets", () => hashedAssets);
|
||||
|
||||
return allAssets;
|
||||
return allAssets;
|
||||
});
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"lang": "en-us",
|
||||
"name": "Adaptive Cards Designer",
|
||||
"short_name": "ACDesigner",
|
||||
"description": "A PWA for the Adaptive Cards Designer",
|
||||
"start_url": "designer/",
|
||||
"background_color": "#3A96DD",
|
||||
"theme_color": "#3A96DD",
|
||||
"orientation": "any",
|
||||
"display": "standalone",
|
||||
"icons": [
|
||||
{
|
||||
"src": "content/icons_blue/blue-512.png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"globDirectory": "public",
|
||||
"globPatterns": [
|
||||
"content/icons/*",
|
||||
"content/icons_blue/*",
|
||||
"content/icons_transparent/*",
|
||||
"content/icons_white",
|
||||
"samples/*.html",
|
||||
"schemas/**",
|
||||
"**/*.css",
|
||||
"designer/*",
|
||||
"manifest.json"
|
||||
],
|
||||
"swDest": "public/service-worker.js",
|
||||
"swSrc": "service-worker.js"
|
||||
}
|
Загрузка…
Ссылка в новой задаче