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