diff --git a/.discoveryrc.app.js b/.discoveryrc.app.js
index 06646bd..c796b25 100644
--- a/.discoveryrc.app.js
+++ b/.discoveryrc.app.js
@@ -2,5 +2,6 @@
module.exports = {
...require('./.discoveryrc.js'),
+ meta: undefined,
data: undefined
};
diff --git a/.discoveryrc.ghpages.js b/.discoveryrc.ghpages.js
new file mode 100644
index 0000000..06646bd
--- /dev/null
+++ b/.discoveryrc.ghpages.js
@@ -0,0 +1,6 @@
+/* eslint-env node */
+
+module.exports = {
+ ...require('./.discoveryrc.js'),
+ data: undefined
+};
diff --git a/.discoveryrc.js b/.discoveryrc.js
index 21ee58d..a620d1e 100644
--- a/.discoveryrc.js
+++ b/.discoveryrc.js
@@ -14,6 +14,10 @@ module.exports = {
prepare: './prepare',
data: './data',
favicon: __dirname + '/app/img/favicon.png',
+ routers: ['./demo/router.js'],
+ meta: {
+ demos: require('./app/demo/index.json')
+ },
view: {
assets: [
'./pages/common.css',
diff --git a/app/demo/chromium.jsonxl b/app/demo/chromium.jsonxl
new file mode 100644
index 0000000..9972e8a
Binary files /dev/null and b/app/demo/chromium.jsonxl differ
diff --git a/app/demo/deno.jsonxl b/app/demo/deno.jsonxl
new file mode 100644
index 0000000..6d4d70d
Binary files /dev/null and b/app/demo/deno.jsonxl differ
diff --git a/app/demo/edge.jsonxl b/app/demo/edge.jsonxl
new file mode 100644
index 0000000..a5cc4f4
Binary files /dev/null and b/app/demo/edge.jsonxl differ
diff --git a/app/demo/index.json b/app/demo/index.json
new file mode 100644
index 0000000..e650367
--- /dev/null
+++ b/app/demo/index.json
@@ -0,0 +1,17 @@
+[
+ {
+ "runtime": "deno",
+ "title": "V8 log (preprocessed)",
+ "url": "demo/deno.jsonxl"
+ },
+ {
+ "runtime": "chromium",
+ "title": "Chromium Profile",
+ "url": "demo/chromium.jsonxl"
+ },
+ {
+ "runtime": "edge",
+ "title": "Edge EPT",
+ "url": "demo/edge.jsonxl"
+ }
+]
diff --git a/app/demo/router.js b/app/demo/router.js
new file mode 100644
index 0000000..4fb7064
--- /dev/null
+++ b/app/demo/router.js
@@ -0,0 +1,15 @@
+/* eslint-env node */
+
+module.exports = function repoHealthPath(app) {
+ const path = require('path');
+ const fs = require('fs');
+ const files = JSON.parse(fs.readFileSync(path.join(__dirname, './index.json')));
+
+ for (const demo of files) {
+ app.get('/' + demo.url, function(req, res) {
+ const filepath = path.join(__dirname, path.basename(demo.url));
+
+ fs.createReadStream(filepath).pipe(res);
+ });
+ }
+};
diff --git a/app/img/runtime-edge.svg b/app/img/runtime-edge.svg
new file mode 100644
index 0000000..b5b7c08
--- /dev/null
+++ b/app/img/runtime-edge.svg
@@ -0,0 +1,2 @@
+
+
diff --git a/app/pages/common.css b/app/pages/common.css
index eeb6bca..3244d3e 100644
--- a/app/pages/common.css
+++ b/app/pages/common.css
@@ -1,3 +1,15 @@
+.discovery-root {
+ --runtime-nodejs: url("../img/runtime-nodejs.png");
+ --runtime-deno: url("../img/runtime-deno.svg");
+ --runtime-chromium: url("../img/runtime-chromium.svg");
+ --runtime-edge: url("../img/runtime-edge.svg");
+ --runtime-electron: url("../img/runtime-electron.svg");
+ --runtime-unknown: url("../img/runtime-v8.svg");
+}
+.discovery-root-darkmode {
+ --runtime-unknown: url("../img/runtime-v8-outline.svg");
+}
+
.view-alert-warning .view-link {
color: inherit;
text-decoration-color: inherit;
diff --git a/app/pages/default.css b/app/pages/default.css
index e708556..5985564 100644
--- a/app/pages/default.css
+++ b/app/pages/default.css
@@ -127,7 +127,10 @@
letter-spacing: 1px;
padding-bottom: 2px;
}
-.page-default .view-page-indicators .runtime:is(.nodejs, .deno, .chromium, .electron, .unknown) .value::before {
+.page-default .view-page-indicators .runtime .value {
+ text-align: left;
+}
+.page-default .view-page-indicators .runtime:is(.nodejs, .deno, .chromium, .edge, .electron, .unknown) .value::before {
content: "";
display: inline-block;
vertical-align: baseline;
@@ -142,25 +145,26 @@
filter: brightness(.85);
}
.page-default .view-page-indicators .runtime:is(.nodejs) .value::before {
- background-image: url("../img/runtime-nodejs.png");
+ background-image: var(--runtime-nodejs);
}
.page-default .view-page-indicators .runtime:is(.deno) .value::before {
- background-image: url("../img/runtime-deno.svg");
+ background-image: var(--runtime-deno);
height: 1.3em;
margin-bottom: -.25em;
margin-right: 0.6ex;
}
+.page-default .view-page-indicators .runtime:is(.edge) .value::before {
+ background-image: var(--runtime-edge);
+ filter: none;
+}
.page-default .view-page-indicators .runtime:is(.chromium) .value::before {
- background-image: url("../img/runtime-chromium.svg");
+ background-image: var(--runtime-chromium);
}
.page-default .view-page-indicators .runtime:is(.electron) .value::before {
- background-image: url("../img/runtime-electron.svg");
+ background-image: var(--runtime-electron);
}
.page-default .view-page-indicators .runtime:is(.unknown) .value::before {
- background-image: url("../img/runtime-v8.svg");
-}
-.discovery-root-darkmode .page-default .view-page-indicators .runtime:is(.unknown) .value::before {
- background-image: url("../img/runtime-v8-outline.svg");
+ background-image: var(--runtime-unknown);
}
.page-default .view-expand.timelines > .header > .header-content {
@@ -325,14 +329,67 @@
font-weight: 200;
font-size: 13px;
}
+.page-default .welcome-page .view-page-header__content h1 {
+ position: relative;
+ top: -11px;
+}
+.page-default .welcome-page .view-page-header__content .description {
+ padding-left: 55px;
+ margin-top: -17px;
+ font-size: 12px;
+ color: #aaa;
+}
.page-default .welcome-page .view-markdown .view-ul {
margin-top: 2px;
}
.page-default .welcome-page .upload-data {
- margin: 2em 0;
+ margin: -8px -15px 15px;
+ background-color: #00000014;
+ border: 1px dashed #555;
+ padding: 12px;
+ border-radius: 7px;
+ max-width: 620px;
}
.page-default .welcome-page .upload-notes {
font-size: 82%;
color: #aaa;
- padding: 6px 0 0 6px;
+ padding: 10px 0 0 3px;
+}
+.page-default .welcome-page .examples {
+ margin-top: 15px;
+}
+.page-default .welcome-page .examples .view-button {
+ margin-top: .35em;
+ margin-left: 0;
+ margin-right: .8ex;
+}
+.page-default .welcome-page .examples .view-button::before {
+ content: "";
+ display: inline-block;
+ vertical-align: middle;
+ height: 1.3em;
+ aspect-ratio: 1/1;
+ background: center no-repeat;
+ background-size: 100%;
+ margin-right: 7px;
+ margin-left: -.5ex;
+ margin-top: -4px;
+}
+.page-default .welcome-page .examples .view-button.nodejs::before {
+ background-image: var(--runtime-nodejs);
+}
+.page-default .welcome-page .examples .view-button.deno::before {
+ background-image: var(--runtime-deno);
+ filter: brightness(.8);
+ height: 1.4em;
+ margin-top: -5px;
+ margin-bottom: -2px;
+}
+.page-default .welcome-page .examples .view-button.chromium::before {
+ background-image: var(--runtime-chromium);
+ filter: brightness(.85);
+}
+.page-default .welcome-page .examples .view-button.edge::before {
+ background-image: var(--runtime-edge);
+ filter: brightness(.95);
}
diff --git a/app/pages/default.js b/app/pages/default.js
index 79025b4..c8cdbb9 100644
--- a/app/pages/default.js
+++ b/app/pages/default.js
@@ -2,6 +2,13 @@
const demoDataBase64 = require('../demo/demo-data-base64.js').default;
const { supportedFormats } = require('../prepare/index.js');
+function consumeDemos() {
+ const demos = discovery.context?.model?.meta?.demos;
+ if (demos) {
+ discovery.action.define('demos', () => demos);
+ }
+}
+
discovery.action.define('uploadDemoData', () => discovery.loadDataFromUrl(demoDataBase64));
setTimeout(() => {
discovery.nav.primary.append({
@@ -16,7 +23,7 @@ setTimeout(() => {
onClick: () => toggleFullPageFlamechart(false)
});
discovery.nav.menu.append({
- when: true,
+ when: '#.actions.unloadData',
content: 'text:"Unload cpuprofile"',
onClick(_, ctx) {
ctx.hide();
@@ -24,7 +31,12 @@ setTimeout(() => {
ctx.widget.setPageHash('');
}
});
+
discovery.nav.render(discovery.dom.nav, discovery.data, discovery.getRenderContext());
+
+ // FIXME: temporary solution, since context is cleaning up on data load/unload
+ discovery.on('data', consumeDemos);
+ consumeDemos();
}, 1);
function toggleFullPageFlamechart(fullpageMode) {
@@ -394,22 +406,14 @@ const noDataPageContent = {
view: 'page-header',
content: [
{ view: 'block', className: 'logo' },
- 'h1:"cpupro"'
- ]
- },
-
- {
- view: 'markdown',
- source: [
- 'A viewer for CPU profiles captured in V8 runtimes like Node.js, Deno or Chromium browsers.',
- '',
- 'Supported formats:',
- ...supportedFormats
+ 'h1:"cpupro"',
+ { view: 'block', className: 'description', content: 'text:"A viewer for CPU profiles captured in V8 runtimes like Node.js, Deno or Chromium browsers"' }
]
},
{
view: 'block',
+ when: '#.actions.uploadFile',
className: 'upload-data',
content: [
'preset/upload',
@@ -422,9 +426,40 @@ const noDataPageContent = {
},
{
- view: 'button',
- onClick: '=#.actions.uploadDemoData',
- content: 'text:"Try demo CPU profile"'
+ view: 'markdown',
+ source: [
+ 'Supported formats:',
+ ...supportedFormats
+ ]
+ },
+
+ {
+ view: 'block',
+ className: 'examples',
+ content: [
+ 'text:"Try out example:"',
+ 'html:"
"',
+ {
+ view: 'button',
+ className: 'nodejs',
+ onClick: '=#.actions.uploadDemoData',
+ content: 'text:"V8 CPU profile"'
+ },
+ {
+ view: 'inline-list',
+ when: '#.actions.demos',
+ data: '"demos".callAction()',
+ whenData: true,
+ item: {
+ view: 'button',
+ className: '=runtime',
+ onClick(_, data) {
+ discovery.loadDataFromUrl(data.url);
+ },
+ content: 'text:title'
+ }
+ }
+ ]
}
]
};
@@ -444,7 +479,8 @@ discovery.page.define('default', {
view: 'h2',
content: [
{ view: 'block', className: 'logo' },
- 'text:#.datasets[].resource | type = "file" ? name : "Untitled profile"'
+ // 'text:#.datasets[].resource | type = "file" ? name : "Untitled profile"'
+ 'md:"data loaded in **{{#.datasets[].timing.responseTime}}** ms"'
]
}
]
diff --git a/package.json b/package.json
index 63d867d..258e56f 100644
--- a/package.json
+++ b/package.json
@@ -37,7 +37,7 @@
"build-wasm": "node scripts/wat-compile.js",
"build-app": "discovery-build --clean --config .discoveryrc.app.js --single-file --no-data --entry-names \"app\"",
"build-report-template": "discovery-build --single-file --no-data --no-model-data-upload --entry-names \"report\"",
- "build-gh-pages": "npm run build-wasm && discovery-build --config .discoveryrc.app.js --single-file --no-data -o .gh-pages",
+ "build-gh-pages": "npm run build-wasm && discovery-build --config .discoveryrc.ghpages.js --single-file --no-data -o .gh-pages && node scripts/gh-pages-files",
"prepublishOnly": "npm run build"
},
"dependencies": {
diff --git a/scripts/gh-pages-files.js b/scripts/gh-pages-files.js
new file mode 100644
index 0000000..b70669a
--- /dev/null
+++ b/scripts/gh-pages-files.js
@@ -0,0 +1,18 @@
+/* eslint-env node */
+
+const path = require('path');
+const fs = require('fs');
+const demosPath = path.join(__dirname, '../app/demo');
+const ghpagesDemosPath = path.join(__dirname, '../.gh-pages/demo');
+
+const indexFile = fs.readFileSync(path.join(demosPath, 'index.json'));
+const indexData = JSON.parse(indexFile);
+
+fs.mkdirSync(ghpagesDemosPath, { recursive: true });
+
+for (const demo of indexData) {
+ fs.cpSync(
+ path.join(demosPath, path.basename(demo.url)),
+ path.join(ghpagesDemosPath, path.basename(demo.url))
+ );
+}