mirror of
https://github.com/wassname/talk.git
synced 2026-09-12 13:01:11 +08:00
Merge branch 'next' of github.com:coralproject/talk into auth-views
* 'next' of github.com:coralproject/talk: [next] Templates (#1760) Adapt typography NO NORMALS
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import CaseSensitivePathsPlugin from "case-sensitive-paths-webpack-plugin";
|
||||
import ExtractTextPlugin from "extract-text-webpack-plugin";
|
||||
import HtmlWebpackPlugin, { Options } from "html-webpack-plugin";
|
||||
import MiniCssExtractPlugin from "mini-css-extract-plugin";
|
||||
import path from "path";
|
||||
import InterpolateHtmlPlugin from "react-dev-utils/InterpolateHtmlPlugin";
|
||||
import WatchMissingNodeModulesPlugin from "react-dev-utils/WatchMissingNodeModulesPlugin";
|
||||
@@ -8,6 +8,7 @@ import TsconfigPathsPlugin from "tsconfig-paths-webpack-plugin";
|
||||
import UglifyJsPlugin from "uglifyjs-webpack-plugin";
|
||||
import webpack, { Configuration } from "webpack";
|
||||
import ManifestPlugin from "webpack-manifest-plugin";
|
||||
|
||||
import paths from "./paths";
|
||||
|
||||
interface CreateWebpackConfig {
|
||||
@@ -59,27 +60,6 @@ export default function createWebpackConfig({
|
||||
},
|
||||
};
|
||||
|
||||
const cssLoaders = [
|
||||
{
|
||||
loader: require.resolve("css-loader"),
|
||||
options: {
|
||||
modules: true,
|
||||
importLoaders: 1,
|
||||
localIdentName: "[name]-[local]-[hash:base64:5]",
|
||||
minimize: isProduction,
|
||||
sourceMap: isProduction && !disableSourcemaps,
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: require.resolve("postcss-loader"),
|
||||
options: {
|
||||
config: {
|
||||
path: paths.appPostCssConfig,
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const localesOptions = {
|
||||
pathToLocales: paths.appLocales,
|
||||
|
||||
@@ -127,13 +107,9 @@ export default function createWebpackConfig({
|
||||
},
|
||||
sourceMap: !disableSourcemaps,
|
||||
}),
|
||||
// Note: this won't work without ExtractTextPlugin.extract(..) in `loaders`.
|
||||
new ExtractTextPlugin({
|
||||
// We use [md5:contenthash:hex:20] instead of [contenthash:8]
|
||||
// because of this bug https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/763.
|
||||
// TODO: Repalce with mini-css-extract-plugin once it supports HMR.
|
||||
// https://github.com/webpack-contrib/mini-css-extract-plugin
|
||||
filename: "assets/css/[name].[md5:contenthash:hex:20].css",
|
||||
new MiniCssExtractPlugin({
|
||||
filename: "assets/css/[name].[hash].css",
|
||||
chunkFilename: "assets/css/[id].[hash].css",
|
||||
}),
|
||||
]
|
||||
: [
|
||||
@@ -316,19 +292,27 @@ export default function createWebpackConfig({
|
||||
// in development "style" loader enables hot editing of CSS.
|
||||
{
|
||||
test: /\.css$/,
|
||||
loader:
|
||||
(isProduction &&
|
||||
ExtractTextPlugin.extract({
|
||||
fallback: styleLoader,
|
||||
use: cssLoaders,
|
||||
})) ||
|
||||
undefined,
|
||||
use:
|
||||
(!isProduction && [
|
||||
require.resolve("style-loader"),
|
||||
...cssLoaders,
|
||||
]) ||
|
||||
undefined,
|
||||
use: [
|
||||
isProduction ? MiniCssExtractPlugin.loader : styleLoader,
|
||||
{
|
||||
loader: require.resolve("css-loader"),
|
||||
options: {
|
||||
modules: true,
|
||||
importLoaders: 1,
|
||||
localIdentName: "[name]-[local]-[hash:base64:5]",
|
||||
minimize: isProduction,
|
||||
sourceMap: isProduction && !disableSourcemaps,
|
||||
},
|
||||
},
|
||||
{
|
||||
loader: require.resolve("postcss-loader"),
|
||||
options: {
|
||||
config: {
|
||||
path: paths.appPostCssConfig,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
// "file" loader makes sure those assets get served by WebpackDevServer.
|
||||
// When you `import` an asset, you get its (virtual) filename.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.root {
|
||||
composes: textField from "talk-ui/shared/typography.css";
|
||||
composes: inputText placeholderPseudo from "talk-ui/shared/typography.css";
|
||||
position: relative;
|
||||
display: block;
|
||||
padding: calc(0.5 * var(--spacing-unit));
|
||||
@@ -24,12 +24,3 @@
|
||||
.fullWidth {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
::placeholder {
|
||||
font-family: var(--font-family);
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
line-height: calc(16rem / var(--rem-base));
|
||||
font-size: calc(16rem / var(--rem-base));
|
||||
color: var(--palette-grey-lighter);
|
||||
}
|
||||
|
||||
@@ -18,5 +18,3 @@ import Flex from '../Flex'
|
||||
<TextField color="error" defaultValue="A TextField with an error" fullWidth/>
|
||||
</Flex>
|
||||
</Playground>
|
||||
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ export interface TextFieldProps {
|
||||
*/
|
||||
placeholder?: string;
|
||||
/**
|
||||
* readOnly
|
||||
* Mark as readonly
|
||||
*/
|
||||
readOnly?: boolean;
|
||||
}
|
||||
|
||||
@@ -59,33 +59,34 @@
|
||||
.heading1 {
|
||||
font-size: calc(24rem / var(--rem-base));
|
||||
font-weight: var(--font-weight-medium);
|
||||
font-family: "Manuale";
|
||||
font-family: var(--font-family-serif);
|
||||
line-height: calc(32em / 24);
|
||||
letter-spacing: calc(0.2em / 16);
|
||||
letter-spacing: calc(0.2em / 24);
|
||||
color: var(--palette-text-primary);
|
||||
}
|
||||
|
||||
.heading2 {
|
||||
font-size: calc(20rem / var(--rem-base));
|
||||
font-weight: var(--font-weight-medium);
|
||||
font-family: "Manuale";
|
||||
font-family: var(--font-family-serif);
|
||||
line-height: calc(24em / 20);
|
||||
letter-spacing: calc(0.2em / 20);
|
||||
color: var(--palette-text-primary);
|
||||
}
|
||||
|
||||
.heading3 {
|
||||
font-size: calc(18rem / var(--rem-base));
|
||||
font-weight: var(--font-weight-medium);
|
||||
font-family: "Manuale";
|
||||
font-family: var(--font-family-serif);
|
||||
line-height: calc(20em / 18);
|
||||
letter-spacing: calc(0.2em / 16);
|
||||
letter-spacing: calc(0.2em / 18);
|
||||
color: var(--palette-text-primary);
|
||||
}
|
||||
|
||||
.heading4 {
|
||||
font-size: calc(16rem / var(--rem-base));
|
||||
font-weight: var(--font-weight-medium);
|
||||
font-family: "Manuale";
|
||||
font-family: var(--font-family-serif);
|
||||
line-height: calc(18em / 16);
|
||||
letter-spacing: calc(0.2em / 16);
|
||||
color: var(--palette-text-primary);
|
||||
@@ -94,7 +95,7 @@
|
||||
.bodyCopy {
|
||||
font-size: calc(16rem / var(--rem-base));
|
||||
font-weight: var(--font-weight-regular);
|
||||
font-family: "Source Sans Pro";
|
||||
font-family: var(--font-family-sans-serif);
|
||||
line-height: calc(18em / 16);
|
||||
letter-spacing: calc(0.2em / 16);
|
||||
color: var(--palette-text-primary);
|
||||
@@ -107,44 +108,44 @@
|
||||
|
||||
.button {
|
||||
color: var(--palette-text-secondary);
|
||||
font-family: "Source Sans Pro";
|
||||
font-family: var(--font-family-sans-serif);
|
||||
font-weight: var(--font-weight-medium);
|
||||
font-size: 14px;
|
||||
line-height: calc(18em / 16);
|
||||
letter-spacing: calc(0.57em / 16);
|
||||
font-size: calc(14rem / var(--rem-base));
|
||||
line-height: calc(18em / 14);
|
||||
letter-spacing: calc(0.57em / 14);
|
||||
}
|
||||
|
||||
.buttonLarge {
|
||||
color: var(--palette-text-secondary);
|
||||
font-family: "Source Sans Pro";
|
||||
font-family: var(--font-family-sans-serif);
|
||||
font-weight: var(--font-weight-medium);
|
||||
font-size: 16px;
|
||||
font-size: calc(16rem / var(--rem-base));
|
||||
line-height: calc(20em / 16);
|
||||
letter-spacing: calc(0.57em / 16);
|
||||
}
|
||||
|
||||
.timestamp {
|
||||
color: var(--palette-text-secondary);
|
||||
font-family: "Source Sans Pro";
|
||||
font-family: var(--font-family-sans-serif);
|
||||
font-weight: var(--font-weight-medium);
|
||||
font-size: 14px;
|
||||
line-height: calc(18em / 16);
|
||||
letter-spacing: calc(0.2em / 16);
|
||||
font-size: calc(14rem / var(--rem-base));
|
||||
line-height: calc(18em / 14);
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
.alertMessage {
|
||||
color: var(--palette-common-black);
|
||||
font-family: var(--font-family);
|
||||
font-family: var(--font-family-sans-serif);
|
||||
font-weight: var(--font-weight-medium);
|
||||
font-size: calc(16rem / var(--rem-base));
|
||||
line-height: normal;
|
||||
letter-spacing: calc(0.2em / 16);
|
||||
line-height: calc(16em / 16);
|
||||
letter-spacing: calc(-0.1em / 16);
|
||||
}
|
||||
|
||||
.textField {
|
||||
font-size: calc(16rem / var(--rem-base));
|
||||
.inputText {
|
||||
font-weight: var(--font-weight-regular);
|
||||
font-family: var(--font-family);
|
||||
font-family: var(--font-family-sans-serif);
|
||||
font-size: calc(16rem / var(--rem-base));
|
||||
line-height: calc(18em / 16);
|
||||
letter-spacing: calc(0.2em / 16);
|
||||
color: var(--palette-text-primary);
|
||||
@@ -153,9 +154,9 @@
|
||||
.inputLabel {
|
||||
font-size: calc(18rem / var(--rem-base));
|
||||
font-weight: var(--font-weight-medium);
|
||||
font-family: "Manuale";
|
||||
line-height: calc(18em / 16);
|
||||
letter-spacing: calc(0.2em / 16);
|
||||
font-family: var(--font-family-serif);
|
||||
line-height: calc(18em / 18);
|
||||
letter-spacing: calc(0.2em / 18);
|
||||
color: var(--palette-text-primary);
|
||||
}
|
||||
|
||||
@@ -169,10 +170,19 @@
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
font-family: var(--font-family);
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
line-height: calc(16rem / var(--rem-base));
|
||||
font-family: var(--font-family-sans-serif);
|
||||
font-weight: var(--font-weight-regular);
|
||||
font-size: calc(16rem / var(--rem-base));
|
||||
line-height: calc(20em / 16);
|
||||
letter-spacing: 0;
|
||||
color: var(--palette-grey-lighter);
|
||||
}
|
||||
|
||||
.placeholderPseudo::placeholder {
|
||||
font-family: var(--font-family-sans-serif);
|
||||
font-weight: var(--font-weight-regular);
|
||||
font-size: calc(16rem / var(--rem-base));
|
||||
line-height: calc(20em / 16);
|
||||
letter-spacing: 0;
|
||||
color: var(--palette-grey-lighter);
|
||||
}
|
||||
|
||||
@@ -64,8 +64,8 @@ const variables = {
|
||||
roundCorners: "2px",
|
||||
/* Typography */
|
||||
remBase: 16,
|
||||
fontFamily: '"Source Sans Pro"',
|
||||
fontSize: 16,
|
||||
fontFamilySansSerif: '"Source Sans Pro"',
|
||||
fontFamilySerif: '"Manuale"',
|
||||
fontWeightLight: 300,
|
||||
fontWeightRegular: 400,
|
||||
fontWeightMedium: 600,
|
||||
|
||||
@@ -14,7 +14,6 @@ export interface SignupBody {
|
||||
username: string;
|
||||
password: string;
|
||||
email: string;
|
||||
displayName?: string;
|
||||
}
|
||||
|
||||
const SignupBodySchema = Joi.object().keys({
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import { RequestHandler } from "express";
|
||||
|
||||
export const streamHandler: RequestHandler = (req, res) => {
|
||||
res.render("stream");
|
||||
};
|
||||
@@ -1,7 +1,10 @@
|
||||
import cons from "consolidate";
|
||||
import { Express } from "express";
|
||||
import http from "http";
|
||||
import { Redis } from "ioredis";
|
||||
import { Db } from "mongodb";
|
||||
import nunjucks from "nunjucks";
|
||||
import path from "path";
|
||||
|
||||
import { Config } from "talk-common/config";
|
||||
import { notFoundMiddleware } from "talk-server/app/middleware/notFound";
|
||||
@@ -29,6 +32,9 @@ export interface AppOptions {
|
||||
* createApp will create a Talk Express app that can be used to handle requests.
|
||||
*/
|
||||
export async function createApp(options: AppOptions): Promise<Express> {
|
||||
// Configure the application.
|
||||
configureApplication(options);
|
||||
|
||||
// Pull the parent out of the options.
|
||||
const { parent } = options;
|
||||
|
||||
@@ -46,7 +52,7 @@ export async function createApp(options: AppOptions): Promise<Express> {
|
||||
);
|
||||
|
||||
// Static Files
|
||||
parent.use(serveStatic);
|
||||
parent.use("/assets", serveStatic);
|
||||
|
||||
// Error Handling
|
||||
parent.use(notFoundMiddleware);
|
||||
@@ -70,6 +76,38 @@ export const listenAndServe = (
|
||||
const httpServer = app.listen(port, () => resolve(httpServer));
|
||||
});
|
||||
|
||||
function configureApplication(options: AppOptions) {
|
||||
const { parent } = options;
|
||||
|
||||
// Trust the first proxy in front of us, this will enable us to trust the fact
|
||||
// that SSL was terminated correctly.
|
||||
parent.set("trust proxy", 1);
|
||||
|
||||
// Setup the view config.
|
||||
setupViews(options);
|
||||
}
|
||||
|
||||
function setupViews(options: AppOptions) {
|
||||
const { parent } = options;
|
||||
|
||||
// configure the default views directory.
|
||||
const views = path.join(__dirname, "..", "..", "..", "static");
|
||||
parent.set("views", views);
|
||||
|
||||
// Reconfigure nunjucks.
|
||||
(cons.requires as any).nunjucks = nunjucks.configure(views, {
|
||||
// In development, we should enable file watch mode.
|
||||
watch: options.config.get("env") === "development",
|
||||
});
|
||||
|
||||
// assign the nunjucks engine to .njk and .html files.
|
||||
parent.engine("njk", cons.nunjucks);
|
||||
parent.engine("html", cons.nunjucks);
|
||||
|
||||
// set .html as the default extension.
|
||||
parent.set("view engine", "html");
|
||||
}
|
||||
|
||||
/**
|
||||
* attachSubscriptionHandlers attaches all the handlers to the http.Server to
|
||||
* handle websocket traffic by upgrading their http connections to websocket.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { RequestHandler } from "express";
|
||||
|
||||
export const notFoundMiddleware: RequestHandler = (req, res, next) => {
|
||||
// FIXME: (wyattjoh) send an error that won't log as crazily as this one does.
|
||||
next(new Error("not found"));
|
||||
};
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import serveStatic from "express-static-gzip";
|
||||
import path from "path";
|
||||
|
||||
export default serveStatic(path.join(__dirname, "..", "..", "dist"), {});
|
||||
const staticPath = path.resolve(
|
||||
path.join(__dirname, "..", "..", "..", "..", "static", "assets")
|
||||
);
|
||||
|
||||
export default serveStatic(staticPath, { index: false });
|
||||
|
||||
@@ -28,6 +28,9 @@ export default (options: MiddlewareOptions) => async (
|
||||
// Attach the tenant to the request.
|
||||
req.tenant = tenant;
|
||||
|
||||
// Attach the tenant to the view locals.
|
||||
res.locals.tenant = tenant;
|
||||
|
||||
next();
|
||||
} catch (err) {
|
||||
next(err);
|
||||
|
||||
@@ -2,6 +2,7 @@ import express from "express";
|
||||
import passport from "passport";
|
||||
|
||||
import { signupHandler } from "talk-server/app/handlers/auth/local";
|
||||
import { streamHandler } from "talk-server/app/handlers/embed/stream";
|
||||
import { apiErrorHandler } from "talk-server/app/middleware/error";
|
||||
import { errorLogger } from "talk-server/app/middleware/logging";
|
||||
import { wrapAuthn } from "talk-server/app/middleware/passport";
|
||||
@@ -134,5 +135,8 @@ export async function createRouter(app: AppOptions, options: RouterOptions) {
|
||||
);
|
||||
}
|
||||
|
||||
// Handle the stream handler.
|
||||
router.get("/embed/stream", streamHandler);
|
||||
|
||||
return router;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user