Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions site/public/_routes.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"version": 1,
"include": ["/utilities", "/utilities/", "/pt-br/utilities", "/pt-br/utilities/", "/libs/javascript/", "/pt-br/libs/javascript/"],
"exclude": []
}
23 changes: 23 additions & 0 deletions site/public/_worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Cloudflare Pages runs this only for the paths in _routes.json; every other request is a static
// file. The old JavaScript docs (docsify) kept a section in the query string: /utilities?id=isvalidcpf
// for a function, /pt-br/utilities?id=cep-e-endereço for a heading. A _redirects rule cannot read
// a query string, so this sends each to its utility's page, from /legacy-ids.json (see
// src/lib/legacy-ids.ts). Without a known id: /utilities goes to the library's page as before, and
// the library's page is served as is.
export default {
async fetch(request, env) {
const url = new URL(request.url);
const pt = url.pathname.startsWith('/pt-br/');
const prefix = pt ? '/pt-br' : '';
const id = url.searchParams.get('id');
if (id) {
const res = await env.ASSETS.fetch(new URL('/legacy-ids.json', url));
if (res.ok) {
const to = (await res.json())[pt ? 'pt-BR' : 'en'][id.toLowerCase()];
if (to) return Response.redirect(new URL(prefix + to, url).toString(), 301);
}
}
if (/^(\/pt-br)?\/utilities\/?$/.test(url.pathname)) return Response.redirect(new URL(`${prefix}/libs/javascript/${url.search}`, url).toString(), 301);
return env.ASSETS.fetch(request);
},
};
9 changes: 9 additions & 0 deletions site/src/app/legacy-ids.json/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// /legacy-ids.json: where each anchor of the old JavaScript docs is now (see lib/legacy-ids.ts).
// public/_worker.js reads it for the old URLs that carry an ?id=.
import { legacyIds } from '@/lib/legacy-ids';

export const dynamic = 'force-static';

export function GET() {
return Response.json(legacyIds());
}
64 changes: 64 additions & 0 deletions site/src/lib/legacy-ids.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Where the old JavaScript docs' anchors are now. That site (docsify) put a section in the query
// string: /utilities?id=isvalidcpf for a function, /utilities?id=cep-e-endereço for a heading. Those
// URLs reach public/_worker.js, which answers with a 301 to the utility's page from this map.
import { loadSpecs, loadStatus } from './data';
import { type Locale, pick } from './i18n';
import { slug } from './prose';

// The old page's section headings that are not a utility's title, in both languages.
const SECTIONS: Record<string, string> = {
'cep-and-address': 'cep',
'cep-e-endereço': 'cep',
pix: 'pix-key',
'nf-e-key': 'nfe-key',
'chave-de-nf-e': 'nfe-key',
'nfs-e-key': 'nfse-key',
'chave-de-nfs-e': 'nfse-key',
pis: 'pis',
'processo-jurídico': 'legal-process',
'bank-accounts-and-banks': 'bank-account',
'contas-bancárias-e-bancos': 'bank-account',
'currency-numbers-and-dates-in-words': 'currency',
'moeda-números-e-datas-por-extenso': 'currency',
'states-and-municipalities': 'state',
'estados-e-municípios': 'state',
'holidays-and-business-days': 'date',
'feriados-e-dias-úteis': 'date',
'voter-id-título-de-eleitor': 'voter-id',
'título-de-eleitor': 'voter-id',
'certidão-civil-registry-certificate': 'certidao',
'cei-cno-and-caepf': 'cei',
'cei-cno-e-caepf': 'cei',
'gtin-product-barcode': 'gtin',
'gtin-código-de-barras-de-produto': 'gtin',
'inscrição-estadual-ie': 'ie',
'e-mail': 'email',
'credit-card': 'credit-card',
'cartão-de-crédito': 'credit-card',
'professional-registration': 'registro-profissional',
'registro-profissional': 'registro-profissional',
vin: 'vin',
};

/** Old anchor (lowercase) → the page, without the language prefix, in each language. */
export function legacyIds() {
const status = loadStatus();
const js = status?.libs?.javascript?.functions ?? {};
const specs = loadSpecs() as any[];
const ids = new Set(specs.map((s) => s.id));
const out = {} as Record<Locale, Record<string, string>>;
for (const locale of ['en', 'pt-BR'] as Locale[]) {
const m: Record<string, string> = {};
for (const [key, id] of Object.entries(SECTIONS)) if (ids.has(id)) m[key] = `/utils/${id}/`;
for (const spec of specs) {
m[spec.id] ??= `/utils/${spec.id}/`;
for (const l of ['en', 'pt-BR'] as Locale[]) m[slug(pick(spec.title, l))] ??= `/utils/${spec.id}/`;
for (const op of spec.operations) {
const symbol = js[op.fnId]?.symbol;
if (symbol) m[symbol.toLowerCase()] = `/utils/${spec.id}/#${slug(pick(op.label, locale))}`;
}
}
out[locale] = m;
}
return out;
}
Loading