mirror of
https://github.com/facebook/docusaurus.git
synced 2025-08-03 16:59:06 +02:00
feat: multiple playground choices (#5207)
* poc of using netlify functions for playground redirections * push * cleanup * restore files * fix netlify functions? * fix netlify functions? * implement serverless functions for playgrounds with persistent cookie * move new.docusaurus.io to monorepo packages * move new.docusaurus.io to monorepo packages * lockfile * push * catch-all redirect * Translate/Interpolate: add better error message if not used correctly * Add /docs/playground page * Add some additional doc
This commit is contained in:
parent
2b5fd2b490
commit
700a82aefe
19 changed files with 1426 additions and 129 deletions
|
@ -1,9 +1,9 @@
|
|||
# new.docusaurus.io
|
||||
|
||||
This is a Netlify deployment that only redirects to the official CodeSandbox template.
|
||||
This is a Netlify deployment to handle the Docusaurus playgrounds shortcut [new.docusaurus.io](https://new.docusaurus.io).
|
||||
|
||||
https://codesandbox.io/s/github/facebook/docusaurus/tree/master/examples/classic
|
||||
We use serverless functions because we want to persist the latest choice of the user in a cookie, so that it redirects directly to the preferred playground next time user visits this link. This is better to do it server-side with cookies and 302 redirects than with client redirects and localStorage.
|
||||
|
||||
The Netlify deployment (Joel can give access): https://app.netlify.com/sites/docusaurus-new/overview
|
||||
Netlify deployment (Joel can give access): https://app.netlify.com/sites/docusaurus-new/overview
|
||||
|
||||
Builds are stopped because we shouldn't need to redeploy the \_redirects file. You can just trigger a manual build if needed.
|
||||
Builds are stopped because we shouldn't need to redeploy very often. You can just trigger a manual build if needed.
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
/* https://codesandbox.io/s/docusaurus
|
77
admin/new.docusaurus.io/functionUtils/playgroundUtils.ts
Normal file
77
admin/new.docusaurus.io/functionUtils/playgroundUtils.ts
Normal file
|
@ -0,0 +1,77 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {HandlerEvent, HandlerResponse} from '@netlify/functions';
|
||||
|
||||
const CookieName = 'DocusaurusPlaygroundName';
|
||||
|
||||
const PlaygroundConfigs = {
|
||||
codesandbox: 'https://codesandbox.io/s/docusaurus',
|
||||
stackblitz: 'https://stackblitz.com/fork/docusaurus',
|
||||
};
|
||||
|
||||
const PlaygroundDocumentationUrl = 'https://docusaurus.io/docs/playground';
|
||||
|
||||
export type PlaygroundName = keyof typeof PlaygroundConfigs;
|
||||
|
||||
function isValidPlaygroundName(
|
||||
playgroundName: string,
|
||||
): playgroundName is PlaygroundName {
|
||||
return Object.keys(PlaygroundConfigs).includes(playgroundName);
|
||||
}
|
||||
|
||||
export function createPlaygroundDocumentationResponse(): HandlerResponse {
|
||||
return {
|
||||
statusCode: 302,
|
||||
headers: {
|
||||
Location: PlaygroundDocumentationUrl,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function createPlaygroundResponse(
|
||||
playgroundName: PlaygroundName,
|
||||
): HandlerResponse {
|
||||
const playgroundUrl = PlaygroundConfigs[playgroundName];
|
||||
return {
|
||||
statusCode: 302,
|
||||
headers: {
|
||||
Location: playgroundUrl,
|
||||
'Set-Cookie': `${CookieName}=${playgroundName}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// Inspired by https://stackoverflow.com/a/3409200/82609
|
||||
function parseCookieString(cookieString: string): Record<string, string> {
|
||||
const result: Record<string, string> = {};
|
||||
cookieString.split(';').forEach(function (cookie) {
|
||||
const [name, value] = cookie.split('=');
|
||||
result[name.trim()] = decodeURI(value);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
export function readPlaygroundName(
|
||||
event: HandlerEvent,
|
||||
): PlaygroundName | undefined {
|
||||
const parsedCookie: Record<string, string> = event.headers.cookie
|
||||
? parseCookieString(event.headers.cookie)
|
||||
: {};
|
||||
const playgroundName: string | undefined = parsedCookie[CookieName];
|
||||
|
||||
if (playgroundName) {
|
||||
if (isValidPlaygroundName(playgroundName)) {
|
||||
return playgroundName;
|
||||
} else {
|
||||
console.error(
|
||||
`playgroundName found in cookie was invalid: ${playgroundName}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
14
admin/new.docusaurus.io/functions/codesandbox.ts
Normal file
14
admin/new.docusaurus.io/functions/codesandbox.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {Handler} from '@netlify/functions';
|
||||
|
||||
import {createPlaygroundResponse} from '../functionUtils/playgroundUtils';
|
||||
|
||||
export const handler: Handler = async function (_event, _context) {
|
||||
return createPlaygroundResponse('codesandbox');
|
||||
};
|
20
admin/new.docusaurus.io/functions/index.ts
Normal file
20
admin/new.docusaurus.io/functions/index.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
import {Handler} from '@netlify/functions';
|
||||
|
||||
import {
|
||||
readPlaygroundName,
|
||||
createPlaygroundResponse,
|
||||
createPlaygroundDocumentationResponse,
|
||||
} from '../functionUtils/playgroundUtils';
|
||||
|
||||
export const handler: Handler = async (event, _context) => {
|
||||
const playgroundName = readPlaygroundName(event);
|
||||
return playgroundName
|
||||
? createPlaygroundResponse(playgroundName)
|
||||
: createPlaygroundDocumentationResponse();
|
||||
};
|
14
admin/new.docusaurus.io/functions/stackblitz.ts
Normal file
14
admin/new.docusaurus.io/functions/stackblitz.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import {Handler} from '@netlify/functions';
|
||||
|
||||
import {createPlaygroundResponse} from '../functionUtils/playgroundUtils';
|
||||
|
||||
export const handler: Handler = async function (_event, _context) {
|
||||
return createPlaygroundResponse('stackblitz');
|
||||
};
|
23
admin/new.docusaurus.io/netlify.toml
Normal file
23
admin/new.docusaurus.io/netlify.toml
Normal file
|
@ -0,0 +1,23 @@
|
|||
|
||||
[functions]
|
||||
directory = "functions"
|
||||
|
||||
[[redirects]]
|
||||
from = "/"
|
||||
to = "/.netlify/functions/index"
|
||||
status = 200
|
||||
|
||||
[[redirects]]
|
||||
from = "/codesandbox"
|
||||
to = "/.netlify/functions/codesandbox"
|
||||
status = 200
|
||||
|
||||
[[redirects]]
|
||||
from = "/stackblitz"
|
||||
to = "/.netlify/functions/stackblitz"
|
||||
status = 200
|
||||
|
||||
[[redirects]]
|
||||
from = "/*"
|
||||
to = "/.netlify/functions/index"
|
||||
status = 200
|
14
admin/new.docusaurus.io/package.json
Normal file
14
admin/new.docusaurus.io/package.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "new.docusaurus.io",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "netlify dev"
|
||||
},
|
||||
"dependencies": {
|
||||
"@netlify/functions": "^0.7.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"netlify-cli": "^5.2.2"
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue