242bc8d111
* Add Backstage logo assets * Update logos.md * Update logos.md * docs/verify-links: allow absolute URLs into microsite/static Co-authored-by: Patrik Oldsberg <poldsberg@gmail.com>
132 lines
3.5 KiB
JavaScript
Executable File
132 lines
3.5 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
/*
|
|
* Copyright 2020 Spotify AB
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
const { resolve: resolvePath, dirname } = require('path');
|
|
const fs = require('fs-extra');
|
|
const recursive = require('recursive-readdir');
|
|
|
|
const projectRoot = resolvePath(__dirname, '..');
|
|
|
|
async function verifyUrl(basePath, url) {
|
|
// Avoid having absolute URL links within docs/, so that links work on the site
|
|
if (
|
|
url.match(
|
|
/https:\/\/github.com\/spotify\/backstage\/(tree|blob)\/master\/docs\//,
|
|
) &&
|
|
basePath.match(/^(?:docs|microsite)\//)
|
|
) {
|
|
return { url, basePath, problem: 'absolute' };
|
|
}
|
|
|
|
url = url.replace(/#.*$/, '');
|
|
url = url.replace(
|
|
/https:\/\/github.com\/spotify\/backstage\/(tree|blob)\/master/,
|
|
'',
|
|
);
|
|
if (!url) {
|
|
return;
|
|
}
|
|
|
|
// Only verify existence of local files for now, so skip anything with a schema
|
|
if (url.match(/[a-z]+:/)) {
|
|
return;
|
|
}
|
|
|
|
let path = '';
|
|
|
|
if (url.startsWith('/')) {
|
|
if (url.startsWith('/docs/') && basePath.match(/^(?:docs|microsite)\//)) {
|
|
return { url, basePath, problem: 'not-relative' };
|
|
}
|
|
|
|
const staticPath = resolvePath(projectRoot, 'microsite/static', `.${url}`);
|
|
if (await fs.pathExists(staticPath)) {
|
|
return;
|
|
}
|
|
|
|
path = resolvePath(projectRoot, `.${url}`);
|
|
} else {
|
|
path = resolvePath(dirname(resolvePath(projectRoot, basePath)), url);
|
|
}
|
|
|
|
const exists = await fs.pathExists(path);
|
|
if (!exists) {
|
|
return { url, basePath, problem: 'missing' };
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
async function verifyFile(filePath) {
|
|
const content = await fs.readFile(filePath, 'utf8');
|
|
const mdLinks = content.match(/\[.+?\]\(.+?\)/g) || [];
|
|
const badUrls = [];
|
|
|
|
for (const mdLink of mdLinks) {
|
|
const url = mdLink.match(/\[.+\]\((.+)\)/)[1].trim();
|
|
const badUrl = await verifyUrl(filePath, url);
|
|
if (badUrl) {
|
|
badUrls.push(badUrl);
|
|
}
|
|
}
|
|
|
|
return badUrls;
|
|
}
|
|
|
|
async function main() {
|
|
process.chdir(projectRoot);
|
|
|
|
const files = await recursive('.', [
|
|
'node_modules',
|
|
'dist',
|
|
'bin',
|
|
'microsite',
|
|
]);
|
|
const mdFiles = files.filter(f => f.endsWith('.md'));
|
|
const badUrls = [];
|
|
|
|
for (const mdFile of mdFiles) {
|
|
const badFileUrls = await verifyFile(mdFile);
|
|
badUrls.push(...badFileUrls);
|
|
}
|
|
|
|
if (badUrls.length) {
|
|
console.log(`Found ${badUrls.length} bad links within repo`);
|
|
for (const { url, basePath, problem } of badUrls) {
|
|
if (problem === 'missing') {
|
|
console.error(
|
|
`Unable to reach ${url} from root or microsite/static/, linked from ${basePath}`,
|
|
);
|
|
} else if (problem === 'not-relative') {
|
|
console.error('Links to /docs/ must be relative');
|
|
console.error(` From: ${basePath}`);
|
|
console.error(` To: ${url}`);
|
|
} else if (problem === 'absolute') {
|
|
console.error(`Link to docs/ should be replaced by a relative URL`);
|
|
console.error(` From: ${basePath}`);
|
|
console.error(` To: ${url}`);
|
|
}
|
|
}
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
main().catch(error => {
|
|
console.error(error.stack);
|
|
process.exit(1);
|
|
});
|