Skip to content
This repository has been archived by the owner on Dec 12, 2024. It is now read-only.

Commit

Permalink
fix: Polyfill script for resolving redirects (#91)
Browse files Browse the repository at this point in the history
From "old" docs structure (pre-#81) onto new one
  • Loading branch information
novusnota authored Mar 7, 2024
1 parent 610f946 commit 7fd0369
Show file tree
Hide file tree
Showing 6 changed files with 220 additions and 73 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/nextjs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ jobs:
${{ runner.os }}-nextjs-${{ hashFiles('**/yarn.lock') }}-
- name: Install dependencies
run: yarn install
run: yarn install --frozen-lockfile

- name: Build documentation
run: yarn build-pages
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test-build-nextjs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ jobs:
${{ runner.os }}-nextjs-${{ hashFiles('**/yarn.lock') }}-
- name: Install dependencies
run: yarn install
run: yarn install --frozen-lockfile

- name: Build documentation
run: yarn build-pages
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ Use Gitpod for a hassle-free cloud-based IDE experience:
1. Clone this GitHub repository.
2. Make sure to have the latest version of [NodeJS LTS](https://nodejs.org/en/download/) installed.
3. Open your terminal in the project directory.
4. Install dependencies:
4. Install dependencies without modifying the `yarn.lock`:

```
yarn
yarn deps
```
5. Start your local development server:
Expand Down
65 changes: 0 additions & 65 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,71 +61,6 @@ export default withNextra({
// defaultLocale: 'default',
// // localeDetection: false,
// },
redirects: () => [
// Language→Guides pages are moved under Book section
{
source: '/language/guides/:page*',
destination: '/book/:page*',
permanent: true,
},

// Getting Started is now a part of Book→Guides sub-section
{
source: '/start',
destination: '/book/guides/getting-started',
permanent: true,
},
{
source: '/start/:slug(first|deploy|test)',
destination: '/book/guides/getting-started/:slug',
permanent: true,
},

// Language→Guides→Grammar is now under Language section as a Specification page
{
source: '/book/grammar',
destination: '/language/spec',
permanent: true,
},

// Evolution section is moved under Language section
{
source: '/evolution',
destination: '/language/evolution/overview',
permanent: true,
},
{
source: '/evolution/:page*',
destination: '/language/evolution/:page*',
permanent: true,
},

// Language→Changelog is merged with the Evolution page
{
source: '/book/changelog',
destination: '/language/evolution/overview',
permanent: true,
},

// Tools are now part of a new Ecosystem section
{
source: '/tools/:page*',
destination: '/ecosystem/tools/:page*',
permanent: true,
},

// Small updates in naming of pages or sub-sections
{
source: '/book/message-modes',
destination: '/book/message-mode',
permanent: true,
},
{
source: '/ecosystem/tools/vs',
destination: '/ecosystem/tools/vscode',
permanent: true,
},
],
webpack(config) {
const allowedSvgRegex = /components\/icons\/.+\.svg$/

Expand Down
9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@
"react-dom": "^18.2.0"
},
"scripts": {
"clean": "rm -fr .next",
"dev": "yarn clean && next",
"build": "yarn clean && next build",
"clean": "rm -fr .next out",
"deps": "yarn install --frozen-lockfile",
"dev": "yarn deps && yarn clean && next",
"build": "yarn deps && yarn clean && next build",
"post-build": "echo 'spell checking, link checking, formatting'",
"build-pages": "yarn build && next export",
"build-pages": "yarn build && next export && node ./scripts/redirects-generate.js",
"next": "next"
},
"devDependencies": {
Expand Down
211 changes: 211 additions & 0 deletions scripts/redirects-generate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
// ----
// TODO: deprecate old links eventually (in 3-6 months from now), and don't create any redirects then.
// ----

import fs from 'fs';
import process from 'process';
import path from 'path';

/* ------------------- */
/* ---- Functions ---- */
/* ------------------- */

/**
* Constructs an HTML redirect page
*
* @param href {string}
* @returns {string}
*/
const constructRedirectPage = (href) =>
`<!DOCTYPE html>
<html>
<head>
<title>Redirecting...</title>
<link rel="canonical" href="${href}" />
<meta charset="utf-8" />
<meta http-equiv="refresh"
content="0; url=${href}" />
</head>
<body>
<p>Redirecting...</p>
</body>
</html>`;

/**
* Produces an array of redirects to be created, taken from next.config.js property with slight modifications.
* Those redirects are essentially a diff of the current structure and the previous one on this commit:
* https://github.com/tact-lang/tact-docs/tree/17176cb5e8bac84163bfa4c7b1bd94c0dc917bea/pages
*
* @returns {{source: string, subSources: string[] | undefined, destination: string}[]}
*/
const getRedirects = () => [
// Language→Guides pages are moved under Book section
{
source: '/language/guides',
subSources: [
'types', 'functions', 'statements', 'constants', 'receive', 'bounced', 'external', 'lifecycle', 'send',
'message', 'deploy', 'debug', 'upgrades', 'masterchain', 'func', 'config', 'programmatic',
],
destination: '/book',
},

// Getting Started is now a part of Book→Guides sub-section
{
source: '/start',
subSources: undefined,
destination: '/book/guides/getting-started',
},
{
source: '/start',
subSources: ['first', 'deploy', 'test'],
destination: '/book/guides/getting-started/:slug',
},

// Language→Guides→Grammar is now under Language section as a Specification page
{
source: '/book/grammar',
subSources: undefined,
destination: '/language/spec',
},

// Evolution section is moved under Language section
{
source: '/evolution',
subSources: undefined,
destination: '/language/evolution/overview',
},
{
source: '/evolution',
subSources: ['OTP-001', 'OTP-002', 'OTP-003', 'OTP-004', 'OTP-005', 'OTP-006'],
destination: '/language/evolution',
},

// Language→Guides→Changelog is merged with the Evolution page
{
source: '/language/guides/changelog',
subSources: undefined,
destination: '/language/evolution/overview',
},

// Tools are now part of a new Ecosystem section
{
source: '/tools',
subSources: ['typescript', 'vs', 'jetbrains'],
destination: '/ecosystem/tools',
},

// Small updates in naming of pages or sub-sections
{
source: '/book/message-modes',
subSources: undefined,
destination: '/book/message-mode',
},
{
source: '/ecosystem/tools/vs',
subSources: undefined,
destination: '/ecosystem/tools/vscode',
},
];

/**
* Checks if the given filepath is a regular page/file and not a redirect page/file
*
* @param filePathWithExt {string}
* @returns bool
*/
const isRegularFile = (filePathWithExt) => {
if (fs.existsSync(filePathWithExt)
&& !(fs.readFileSync(filePathWithExt, 'utf8').includes('<title>Redirecting...</title>'))) {
return true;
}

return false;
};

/**
* Creates the redirect file, unless there exists a regular page/file under source path already.
* Returns true if the redirect file was created and false otherwise.
*
* @param source {string}
* @param destination {string}
* @returns bool
*/
const createRedirectFile = (source, destination) => {
// full path, minus the extension
const pathUntilExt = path.join(cwd, '/out', source);

// full path with extension
const pathWithExt = pathUntilExt + '.html';

// if file exists, but doesn't include the line from the redirect page
if (isRegularFile(pathWithExt)) {
console.log(`Warning: such path (${pathWithExt}) already exists in the docs, so redirect from it was NOT created`);
return false;
}

// need to create additional dirs
if (source.split('/').length > 1) {
const nestedDir = path.dirname(pathUntilExt);
// NOTE: debug output
// console.log(nestedDir, redirect.source);
fs.mkdirSync(nestedDir, { recursive: true });
}

// create the redirect file
fs.writeFileSync(pathWithExt, constructRedirectPage(destination));

// report success
return true;
};

/* ---------------- */
/* ---- Script ---- */
/* ---------------- */

const cwd = process.cwd(); // current working directory of the process

// Not in the root dir of the repo
if (!cwd.endsWith('tact-docs')) {
console.log(`Error: not running from the root directory of the repo, but from ${cwd}`);
process.exit(1);
}

// out/ doesn't exist
if (!fs.existsSync(path.join(cwd, '/out'))) {
console.log(`Error: out/ dir doesn't exist, try building it first`);
process.exit(1);
}

// get a list of redirects
const redirects = getRedirects();

// count expected number of redirects to be created
let expectedCount = 0;
for (const redirect of redirects) {
expectedCount += (redirect.subSources?.length ?? 1);
}

// log start
console.log(`Started generating redirects. Expected count: ${expectedCount}`);

// for each redirect create redirect file(s) and/or missing folder(s)
let count = 0;
for (const redirect of redirects) {
// 1. have no nested sub-sources
if (redirect.subSources === undefined) {
if (createRedirectFile(redirect.source, redirect.destination) === true) {
count += 1;
}
continue;
}

// 2. have some nested structure
for (const subSource of redirect.subSources) {
if (createRedirectFile(redirect.source + '/' + subSource, redirect.destination + '/' + subSource)) {
count += 1;
}
}
}

// log end
console.log(`Finished generating redirects. Actually generated: ${count}`);

0 comments on commit 7fd0369

Please sign in to comment.