Update SEO for non-binary markets
This commit is contained in:
parent
8e33c2b639
commit
0a3b14883c
|
@ -1,10 +1,10 @@
|
|||
import { IncomingMessage } from "http";
|
||||
import { parse } from "url";
|
||||
import { ParsedRequest } from "./types";
|
||||
import { IncomingMessage } from 'http'
|
||||
import { parse } from 'url'
|
||||
import { ParsedRequest } from './types'
|
||||
|
||||
export function parseRequest(req: IncomingMessage) {
|
||||
console.log("HTTP " + req.url);
|
||||
const { pathname, query } = parse(req.url || "/", true);
|
||||
console.log('HTTP ' + req.url)
|
||||
const { pathname, query } = parse(req.url || '/', true)
|
||||
const {
|
||||
fontSize,
|
||||
images,
|
||||
|
@ -20,73 +20,73 @@ export function parseRequest(req: IncomingMessage) {
|
|||
creatorName,
|
||||
creatorUsername,
|
||||
creatorAvatarUrl,
|
||||
} = query || {};
|
||||
} = query || {}
|
||||
|
||||
if (Array.isArray(fontSize)) {
|
||||
throw new Error("Expected a single fontSize");
|
||||
throw new Error('Expected a single fontSize')
|
||||
}
|
||||
if (Array.isArray(theme)) {
|
||||
throw new Error("Expected a single theme");
|
||||
throw new Error('Expected a single theme')
|
||||
}
|
||||
|
||||
const arr = (pathname || "/").slice(1).split(".");
|
||||
let extension = "";
|
||||
let text = "";
|
||||
const arr = (pathname || '/').slice(1).split('.')
|
||||
let extension = ''
|
||||
let text = ''
|
||||
if (arr.length === 0) {
|
||||
text = "";
|
||||
text = ''
|
||||
} else if (arr.length === 1) {
|
||||
text = arr[0];
|
||||
text = arr[0]
|
||||
} else {
|
||||
extension = arr.pop() as string;
|
||||
text = arr.join(".");
|
||||
extension = arr.pop() as string
|
||||
text = arr.join('.')
|
||||
}
|
||||
|
||||
// Take a url query param and return a single string
|
||||
const getString = (stringOrArray: string[] | string | undefined): string => {
|
||||
if (Array.isArray(stringOrArray)) {
|
||||
// If the query param is an array, return the first element
|
||||
return stringOrArray[0];
|
||||
return stringOrArray[0]
|
||||
}
|
||||
return stringOrArray || "";
|
||||
};
|
||||
return stringOrArray || ''
|
||||
}
|
||||
|
||||
const parsedRequest: ParsedRequest = {
|
||||
fileType: extension === "jpeg" ? extension : "png",
|
||||
fileType: extension === 'jpeg' ? extension : 'png',
|
||||
text: decodeURIComponent(text),
|
||||
theme: theme === "dark" ? "dark" : "light",
|
||||
md: md === "1" || md === "true",
|
||||
fontSize: fontSize || "96px",
|
||||
theme: theme === 'dark' ? 'dark' : 'light',
|
||||
md: md === '1' || md === 'true',
|
||||
fontSize: fontSize || '96px',
|
||||
images: getArray(images),
|
||||
widths: getArray(widths),
|
||||
heights: getArray(heights),
|
||||
|
||||
question:
|
||||
getString(question) || "Will you create a prediction market on Manifold?",
|
||||
probability: getString(probability) || "85%",
|
||||
metadata: getString(metadata) || "Jan 1 • M$ 123 pool",
|
||||
creatorName: getString(creatorName) || "Manifold Markets",
|
||||
creatorUsername: getString(creatorUsername) || "ManifoldMarkets",
|
||||
creatorAvatarUrl: getString(creatorAvatarUrl) || "",
|
||||
};
|
||||
parsedRequest.images = getDefaultImages(parsedRequest.images);
|
||||
return parsedRequest;
|
||||
getString(question) || 'Will you create a prediction market on Manifold?',
|
||||
probability: getString(probability),
|
||||
metadata: getString(metadata) || 'Jan 1 • M$ 123 pool',
|
||||
creatorName: getString(creatorName) || 'Manifold Markets',
|
||||
creatorUsername: getString(creatorUsername) || 'ManifoldMarkets',
|
||||
creatorAvatarUrl: getString(creatorAvatarUrl) || '',
|
||||
}
|
||||
parsedRequest.images = getDefaultImages(parsedRequest.images)
|
||||
return parsedRequest
|
||||
}
|
||||
|
||||
function getArray(stringOrArray: string[] | string | undefined): string[] {
|
||||
if (typeof stringOrArray === "undefined") {
|
||||
return [];
|
||||
if (typeof stringOrArray === 'undefined') {
|
||||
return []
|
||||
} else if (Array.isArray(stringOrArray)) {
|
||||
return stringOrArray;
|
||||
return stringOrArray
|
||||
} else {
|
||||
return [stringOrArray];
|
||||
return [stringOrArray]
|
||||
}
|
||||
}
|
||||
|
||||
function getDefaultImages(images: string[]): string[] {
|
||||
const defaultImage = "https://manifold.markets/logo.png";
|
||||
const defaultImage = 'https://manifold.markets/logo.png'
|
||||
|
||||
if (!images || !images[0]) {
|
||||
return [defaultImage];
|
||||
return [defaultImage]
|
||||
}
|
||||
return images;
|
||||
return images
|
||||
}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import { sanitizeHtml } from "./sanitizer";
|
||||
import { ParsedRequest } from "./types";
|
||||
import { sanitizeHtml } from './sanitizer'
|
||||
import { ParsedRequest } from './types'
|
||||
|
||||
function getCss(theme: string, fontSize: string) {
|
||||
let background = "white";
|
||||
let foreground = "black";
|
||||
let radial = "lightgray";
|
||||
let background = 'white'
|
||||
let foreground = 'black'
|
||||
let radial = 'lightgray'
|
||||
|
||||
if (theme === "dark") {
|
||||
background = "black";
|
||||
foreground = "white";
|
||||
radial = "dimgray";
|
||||
if (theme === 'dark') {
|
||||
background = 'black'
|
||||
foreground = 'white'
|
||||
radial = 'dimgray'
|
||||
}
|
||||
// To use Readex Pro: `font-family: 'Readex Pro', sans-serif;`
|
||||
return `
|
||||
|
@ -78,7 +78,7 @@ function getCss(theme: string, fontSize: string) {
|
|||
.text-primary {
|
||||
color: #11b981;
|
||||
}
|
||||
`;
|
||||
`
|
||||
}
|
||||
|
||||
export function getHtml(parsedReq: ParsedRequest) {
|
||||
|
@ -92,8 +92,8 @@ export function getHtml(parsedReq: ParsedRequest) {
|
|||
creatorName,
|
||||
creatorUsername,
|
||||
creatorAvatarUrl,
|
||||
} = parsedReq;
|
||||
const hideAvatar = creatorAvatarUrl ? "" : "hidden";
|
||||
} = parsedReq
|
||||
const hideAvatar = creatorAvatarUrl ? '' : 'hidden'
|
||||
return `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
|
@ -145,7 +145,7 @@ export function getHtml(parsedReq: ParsedRequest) {
|
|||
</div>
|
||||
<div class="flex flex-col text-primary">
|
||||
<div class="text-8xl">${probability}</div>
|
||||
<div class="text-4xl">chance</div>
|
||||
<div class="text-4xl">${probability !== '' ? 'chance' : ''}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -157,5 +157,5 @@ export function getHtml(parsedReq: ParsedRequest) {
|
|||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>`;
|
||||
</html>`
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import Head from 'next/head'
|
|||
|
||||
export type OgCardProps = {
|
||||
question: string
|
||||
probability: string
|
||||
probability?: string
|
||||
metadata: string
|
||||
creatorName: string
|
||||
creatorUsername: string
|
||||
|
@ -11,11 +11,16 @@ export type OgCardProps = {
|
|||
}
|
||||
|
||||
function buildCardUrl(props: OgCardProps) {
|
||||
const probabilityParam =
|
||||
props.probability === undefined
|
||||
? ''
|
||||
: `&probability=${encodeURIComponent(props.probability ?? '')}`
|
||||
|
||||
// URL encode each of the props, then add them as query params
|
||||
return (
|
||||
`https://manifold-og-image.vercel.app/m.png` +
|
||||
`?question=${encodeURIComponent(props.question)}` +
|
||||
`&probability=${encodeURIComponent(props.probability)}` +
|
||||
probabilityParam +
|
||||
`&metadata=${encodeURIComponent(props.metadata)}` +
|
||||
`&creatorName=${encodeURIComponent(props.creatorName)}` +
|
||||
`&creatorUsername=${encodeURIComponent(props.creatorUsername)}`
|
||||
|
|
|
@ -102,8 +102,7 @@ export default function ContractPage(props: {
|
|||
const allowResolve = !isResolved && isCreator && !!user
|
||||
const hasSidePanel = isBinary && (allowTrade || allowResolve)
|
||||
|
||||
// TODO(James): Create SEO props for non-binary contracts.
|
||||
const ogCardProps = isBinary ? getOpenGraphProps(contract) : undefined
|
||||
const ogCardProps = getOpenGraphProps(contract)
|
||||
|
||||
return (
|
||||
<Page wide={hasSidePanel}>
|
||||
|
@ -191,8 +190,10 @@ function BetsSection(props: {
|
|||
}
|
||||
|
||||
const getOpenGraphProps = (contract: Contract) => {
|
||||
const { resolution, question, creatorName, creatorUsername } = contract
|
||||
const probPercent = getBinaryProbPercent(contract)
|
||||
const { resolution, question, creatorName, creatorUsername, outcomeType } =
|
||||
contract
|
||||
const probPercent =
|
||||
outcomeType === 'BINARY' ? getBinaryProbPercent(contract) : undefined
|
||||
|
||||
const description = resolution
|
||||
? `Resolved ${resolution}. ${contract.description}`
|
||||
|
|
Loading…
Reference in New Issue
Block a user