mirror of
https://github.com/mifi/lossless-cut.git
synced 2026-10-25 17:42:19 +08:00
The losslesscut.app website moves into website/ (previously its own repo, deployed to S3/CloudFront) and is built with Astro + Starlight, deployed with Cloudflare Workers Builds (production from master, a preview URL per branch and pull request). See website/README.md. - docs/*.md become pages under /docs. They stay plain markdown for GitHub: a content loader generates the front matter, remark plugins rewrite links, and the build fails on links to missing pages or headings. - The app's links go through https://losslesscut.app/go/<name> redirects (src/common/websiteUrls.ts), so targets can move without an app update. The build checks that each target page and #anchor exists. This covers the help pages, discussions, bug reports, feature requests, thanks, Discord, the privacy policy, licenses.txt and the update check (/go/latest-release, a fetch replacing @octokit/core). - licenses.txt is generated and attached to each GitHub release by the release workflow. - New privacy policy at /privacy-policy. - The homepage is a React component rendered to static HTML, with a header, Download/Documentation buttons and social icons. Its images and icons are served from the site (camera metadata stripped), without Google Fonts. - Official links are in src/common/links.ts (app) and website/src/links.ts (website). - The error report dialog's Discord link opened GitHub. - Docs: fix broken links. Release notes: list each changelog line once. Changelog: Help links open the documentation on losslesscut.app Changelog: The Discord link in the error report dialog now opens Discord instead of GitHub Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AntZvg7M7on4kAETvpYqzp Co-authored-by: Mikael Finstad <finstaden@gmail.com>
45 lines
2.4 KiB
TypeScript
45 lines
2.4 KiB
TypeScript
// Writes the redirects for the app's links to the website (https://losslesscut.app/go/<name>, see
|
|
// src/common/websiteUrls.ts) into the built site (dist/_redirects), and checks that each target page (and #anchor) exists.
|
|
import fs from 'node:fs/promises';
|
|
|
|
// the app's list, shared through the repo rather than as a package
|
|
// eslint-disable-next-line import/no-relative-packages
|
|
import { appLinkPrefix, appLinkTargets, websiteUrl } from '../../src/common/websiteUrls.ts';
|
|
|
|
const distDir = new URL('../dist/', import.meta.url);
|
|
|
|
// with trailingSlash: 'never', /docs/cli is served from docs/cli/index.html (see astro.config.ts)
|
|
const getHtmlFile = (pathname: string) => new URL(`.${pathname.replace(/\/$/, '')}/index.html`, distDir);
|
|
|
|
const escapeRegExp = (text: string) => text.replaceAll(/[$()*+.?[\\\]^{|}]/g, String.raw`\$&`);
|
|
// an element with this id, e.g. <h2 id="faq">, not just the text id="faq" somewhere (e.g. in data-id="faq")
|
|
const hasElementWithId = (html: string, id: string) => new RegExp(`<[a-z][^>]*\\sid="${escapeRegExp(id)}"`, 'i').test(html);
|
|
|
|
const problems: string[] = [];
|
|
await Promise.all(Object.entries(appLinkTargets).map(async ([name, target]) => {
|
|
const { origin, pathname, hash } = new URL(target, websiteUrl);
|
|
// targets on other sites (like a GitHub release asset) can't be checked here
|
|
if (origin !== websiteUrl) return;
|
|
let html: string;
|
|
try {
|
|
html = await fs.readFile(getHtmlFile(pathname), 'utf8');
|
|
} catch {
|
|
problems.push(`${name}: ${target}: page not found`);
|
|
return;
|
|
}
|
|
if (hash !== '' && !hasElementWithId(html, decodeURIComponent(hash.slice(1)))) {
|
|
problems.push(`${name}: ${target}: no element with this id on the page`);
|
|
}
|
|
}));
|
|
|
|
if (problems.length > 0) {
|
|
console.error(`The app links to website pages that don't exist (see src/common/websiteUrls.ts):\n${problems.sort().join('\n')}`);
|
|
process.exitCode = 1;
|
|
} else {
|
|
// https://developers.cloudflare.com/workers/static-assets/redirects/
|
|
// 302, because the targets may change, and browsers would remember a 301
|
|
const redirects = Object.entries(appLinkTargets).map(([name, target]) => `${appLinkPrefix}${name} ${target} 302`);
|
|
await fs.appendFile(new URL('_redirects', distDir), `# Links from the app, see src/common/websiteUrls.ts\n${redirects.join('\n')}\n`);
|
|
console.log(`Wrote redirects for the ${redirects.length} links from the app, and checked that their pages exist.`);
|
|
}
|