Better dev server integration
This commit is contained in:
56
server/components/DirectoryListing.js
Normal file
56
server/components/DirectoryListing.js
Normal file
@ -0,0 +1,56 @@
|
||||
const React = require("react");
|
||||
const prettyBytes = require("pretty-bytes");
|
||||
const getFileContentType = require("../utils/getFileContentType");
|
||||
|
||||
const e = React.createElement;
|
||||
|
||||
const formatTime = time => new Date(time).toISOString();
|
||||
|
||||
function DirectoryListing({ dir, entries }) {
|
||||
const rows = entries.map(({ file, stats }, index) => {
|
||||
const isDir = stats.isDirectory();
|
||||
const href = file + (isDir ? "/" : "");
|
||||
|
||||
return e(
|
||||
"tr",
|
||||
{ key: file, className: index % 2 ? "odd" : "even" },
|
||||
e("td", null, e("a", { title: file, href }, file)),
|
||||
e("td", null, isDir ? "-" : getFileContentType(file)),
|
||||
e("td", null, isDir ? "-" : prettyBytes(stats.size)),
|
||||
e("td", null, isDir ? "-" : formatTime(stats.mtime))
|
||||
);
|
||||
});
|
||||
|
||||
if (dir !== "/") {
|
||||
rows.unshift(
|
||||
e(
|
||||
"tr",
|
||||
{ key: "..", className: "odd" },
|
||||
e("td", null, e("a", { title: "Parent directory", href: "../" }, "..")),
|
||||
e("td", null, "-"),
|
||||
e("td", null, "-"),
|
||||
e("td", null, "-")
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return e(
|
||||
"table",
|
||||
null,
|
||||
e(
|
||||
"thead",
|
||||
null,
|
||||
e(
|
||||
"tr",
|
||||
null,
|
||||
e("th", null, "Name"),
|
||||
e("th", null, "Type"),
|
||||
e("th", null, "Size"),
|
||||
e("th", null, "Last Modified")
|
||||
)
|
||||
),
|
||||
e("tbody", null, rows)
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = DirectoryListing;
|
43
server/components/IndexPage.css
Normal file
43
server/components/IndexPage.css
Normal file
@ -0,0 +1,43 @@
|
||||
body {
|
||||
font-size: 16px;
|
||||
font-family: -apple-system,
|
||||
BlinkMacSystemFont,
|
||||
"Segoe UI",
|
||||
Roboto,
|
||||
Helvetica,
|
||||
Arial,
|
||||
sans-serif;
|
||||
line-height: 1.5;
|
||||
padding: 0px 10px 5px;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font: 0.85em Monaco, monospace;
|
||||
}
|
||||
tr.even {
|
||||
background-color: #eee;
|
||||
}
|
||||
th {
|
||||
text-align: left;
|
||||
}
|
||||
th, td {
|
||||
padding: 0.25em 0.5em;
|
||||
}
|
||||
|
||||
.content-wrapper {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.version-wrapper {
|
||||
line-height: 2.25em;
|
||||
float: right;
|
||||
}
|
||||
#version {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
address {
|
||||
text-align: right;
|
||||
}
|
56
server/components/IndexPage.js
Normal file
56
server/components/IndexPage.js
Normal file
@ -0,0 +1,56 @@
|
||||
const React = require("react");
|
||||
const semver = require("semver");
|
||||
const DirectoryListing = require("./DirectoryListing");
|
||||
const readCSS = require("../utils/readCSS");
|
||||
|
||||
const e = React.createElement;
|
||||
|
||||
const IndexPageStyle = readCSS(__dirname, "IndexPage.css");
|
||||
const IndexPageScript = `
|
||||
var s = document.getElementById('version'), v = s.value
|
||||
s.onchange = function () {
|
||||
window.location.href = window.location.href.replace('@' + v, '@' + s.value)
|
||||
}
|
||||
`;
|
||||
|
||||
const byVersion = (a, b) => (semver.lt(a, b) ? -1 : semver.gt(a, b) ? 1 : 0);
|
||||
|
||||
function IndexPage({ packageInfo, version, dir, entries }) {
|
||||
const versions = Object.keys(packageInfo.versions).sort(byVersion);
|
||||
const options = versions.map(v =>
|
||||
e("option", { key: v, value: v }, `${packageInfo.name}@${v}`)
|
||||
);
|
||||
|
||||
return e(
|
||||
"html",
|
||||
null,
|
||||
e(
|
||||
"head",
|
||||
null,
|
||||
e("meta", { charSet: "utf-8" }),
|
||||
e("title", null, `Index of ${dir}`),
|
||||
e("style", { dangerouslySetInnerHTML: { __html: IndexPageStyle } })
|
||||
),
|
||||
e(
|
||||
"body",
|
||||
null,
|
||||
e(
|
||||
"div",
|
||||
{ className: "content-wrapper" },
|
||||
e(
|
||||
"div",
|
||||
{ className: "version-wrapper" },
|
||||
e("select", { id: "version", defaultValue: version }, options)
|
||||
),
|
||||
e("h1", null, `Index of ${dir}`),
|
||||
e("script", { dangerouslySetInnerHTML: { __html: IndexPageScript } }),
|
||||
e("hr"),
|
||||
e(DirectoryListing, { dir, entries }),
|
||||
e("hr"),
|
||||
e("address", null, `${packageInfo.name}@${version}`)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = IndexPage;
|
76
server/components/MainPage.js
Normal file
76
server/components/MainPage.js
Normal file
@ -0,0 +1,76 @@
|
||||
const React = require("react");
|
||||
const PropTypes = require("prop-types");
|
||||
|
||||
const e = React.createElement;
|
||||
|
||||
function MainPage({
|
||||
title,
|
||||
description,
|
||||
scripts,
|
||||
styles,
|
||||
webpackManifest,
|
||||
content
|
||||
}) {
|
||||
return e(
|
||||
"html",
|
||||
{ lang: "en" },
|
||||
e(
|
||||
"head",
|
||||
null,
|
||||
e("meta", { charSet: "utf-8" }),
|
||||
e("title", null, title),
|
||||
e("meta", { httpEquiv: "X-UA-Compatible", content: "IE=edge,chrome=1" }),
|
||||
e("meta", { name: "description", content: description }),
|
||||
e("meta", {
|
||||
name: "viewport",
|
||||
content: "width=device-width,initial-scale=1,maximum-scale=1"
|
||||
}),
|
||||
e("meta", { name: "timestamp", content: new Date().toISOString() }),
|
||||
e("link", { rel: "shortcut icon", href: "/favicon.ico" }),
|
||||
e("script", {
|
||||
dangerouslySetInnerHTML: {
|
||||
__html:
|
||||
"window.Promise || document.write('\\x3Cscript src=\"/_polyfills/es6-promise.min.js\">\\x3C/script>\\x3Cscript>ES6Promise.polyfill()\\x3C/script>')"
|
||||
}
|
||||
}),
|
||||
e("script", {
|
||||
dangerouslySetInnerHTML: {
|
||||
__html:
|
||||
"window.fetch || document.write('\\x3Cscript src=\"/_polyfills/fetch.min.js\">\\x3C/script>')"
|
||||
}
|
||||
}),
|
||||
e("script", {
|
||||
dangerouslySetInnerHTML: {
|
||||
__html: "window.webpackManifest = " + JSON.stringify(webpackManifest)
|
||||
}
|
||||
}),
|
||||
styles.map(s => e("link", { key: s, rel: "stylesheet", href: s }))
|
||||
),
|
||||
e(
|
||||
"body",
|
||||
null,
|
||||
e("div", { id: "app", dangerouslySetInnerHTML: { __html: content } }),
|
||||
scripts.map(s => e("script", { key: s, src: s }))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
MainPage.propTypes = {
|
||||
title: PropTypes.string,
|
||||
description: PropTypes.string,
|
||||
scripts: PropTypes.arrayOf(PropTypes.string),
|
||||
styles: PropTypes.arrayOf(PropTypes.string),
|
||||
webpackManifest: PropTypes.object,
|
||||
content: PropTypes.string
|
||||
};
|
||||
|
||||
MainPage.defaultProps = {
|
||||
title: "UNPKG",
|
||||
description: "The CDN for everything on npm",
|
||||
scripts: [],
|
||||
styles: [],
|
||||
webpackManifest: {},
|
||||
content: ""
|
||||
};
|
||||
|
||||
module.exports = MainPage;
|
Reference in New Issue
Block a user