Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DOC-305: orphan pages detector #428

Draft
wants to merge 55 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
a628b9d
latest supported platform
fantkolja Sep 2, 2024
fbbca51
include version branches
fantkolja Sep 2, 2024
ddbf816
include version branches
fantkolja Sep 2, 2024
0e16ef5
include version branches
fantkolja Sep 2, 2024
e68fc68
include version branches
fantkolja Sep 2, 2024
72d8482
correct 5.5. version MC
fantkolja Sep 2, 2024
40ddbe9
correct 5.5. version MC
fantkolja Sep 2, 2024
b46319d
Merge branch 'hazelcast:main' into main
fantkolja Sep 2, 2024
aba5cb0
Merge branch 'hazelcast:main' into main
fantkolja Sep 4, 2024
b935a50
Merge branch 'hazelcast:main' into main
fantkolja Sep 10, 2024
603c385
Merge branch 'hazelcast:main' into main
fantkolja Oct 16, 2024
4dabc73
Merge branch 'hazelcast:main' into main
fantkolja Nov 15, 2024
4a32a17
Merge remote-tracking branch 'upstream/main'
fantkolja Nov 25, 2024
54d09c7
Merge remote-tracking branch 'upstream/main'
fantkolja Nov 26, 2024
b2aee57
Merge remote-tracking branch 'upstream/main'
fantkolja Nov 27, 2024
d9615c5
Merge remote-tracking branch 'upstream/main'
fantkolja Dec 5, 2024
e62a1ce
add orphan pages checker
fantkolja Dec 10, 2024
c8f45ff
add orphan pages checker
fantkolja Dec 11, 2024
7dd4020
copy scripts from hazelcast-docs
fantkolja Dec 11, 2024
040d05a
copy scripts from hazelcast-docs
fantkolja Dec 12, 2024
fed0d90
copy scripts from hazelcast-docs
fantkolja Dec 12, 2024
6471231
copy scripts from hazelcast-docs
fantkolja Dec 12, 2024
96af6ac
copy scripts from hazelcast-docs
fantkolja Dec 12, 2024
d7a45a8
copy scripts from hazelcast-docs
fantkolja Dec 12, 2024
c529c48
copy scripts from hazelcast-docs
fantkolja Dec 12, 2024
aed3bc2
copy scripts from hazelcast-docs
fantkolja Dec 12, 2024
1ef1bb0
copy scripts from hazelcast-docs
fantkolja Dec 12, 2024
bb9fb5c
copy scripts from hazelcast-docs
fantkolja Dec 12, 2024
4ed9964
copy scripts from hazelcast-docs
fantkolja Dec 12, 2024
c666e6b
copy scripts from hazelcast-docs
fantkolja Dec 12, 2024
4031d9e
copy scripts from hazelcast-docs
fantkolja Dec 13, 2024
7e3ef16
copy scripts from hazelcast-docs
fantkolja Dec 13, 2024
3859dc8
copy scripts from hazelcast-docs
fantkolja Dec 13, 2024
15c0e2a
copy scripts from hazelcast-docs
fantkolja Dec 13, 2024
2c519ff
copy scripts from hazelcast-docs
fantkolja Dec 13, 2024
563b83d
copy scripts from hazelcast-docs
fantkolja Dec 13, 2024
3fb35e0
copy scripts from hazelcast-docs
fantkolja Dec 13, 2024
51b64a7
copy scripts from hazelcast-docs
fantkolja Dec 13, 2024
6fb951b
copy scripts from hazelcast-docs
fantkolja Dec 13, 2024
5325e9c
copy scripts from hazelcast-docs
fantkolja Dec 13, 2024
e34e6cc
copy scripts from hazelcast-docs
fantkolja Dec 16, 2024
5bbeb46
copy scripts from hazelcast-docs
fantkolja Dec 16, 2024
200532c
copy scripts from hazelcast-docs
fantkolja Dec 16, 2024
aa1a434
copy scripts from hazelcast-docs
fantkolja Dec 16, 2024
3a8de6f
copy scripts from hazelcast-docs
fantkolja Dec 16, 2024
0c5b00f
copy scripts from hazelcast-docs
fantkolja Dec 16, 2024
9e70daf
copy scripts from hazelcast-docs
fantkolja Dec 16, 2024
257499e
copy scripts from hazelcast-docs
fantkolja Dec 16, 2024
8dcd407
copy scripts from hazelcast-docs
fantkolja Dec 16, 2024
93ac0c7
copy scripts from hazelcast-docs
fantkolja Dec 16, 2024
1b88863
copy scripts from hazelcast-docs
fantkolja Dec 16, 2024
f66f682
copy scripts from hazelcast-docs
fantkolja Dec 16, 2024
88a8191
copy scripts from hazelcast-docs
fantkolja Dec 16, 2024
2f892ae
copy scripts from hazelcast-docs
fantkolja Dec 16, 2024
7d7acf1
copy scripts from hazelcast-docs
fantkolja Dec 16, 2024
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
3 changes: 3 additions & 0 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,6 @@ jobs:
uses: actions/checkout@v4
- name: Check dead links
uses: hazelcast/hazelcast-docs/.github/actions/validate@main
- name: Check orphan pages
shell: bash
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit - not sure if neccesary.

run: npm run check-orphan-pages
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to install a specific version of node?

2 changes: 1 addition & 1 deletion docs/modules/getting-started/partials/nav.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
** User Interface Overview
*** xref:getting-started:user-interface.adoc[Top Bar and Side Bar]
*** xref:getting-started:graphs.adoc[]
*** xref:getting-started:tables.adoc[]
*** xref:getting-started:tables.adoc[]
107 changes: 107 additions & 0 deletions orphan-pages-checker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// @TODO: if we go with this approach, we DEFINITELY need an npm package
// containing all our helper extensions and scripts
// it can be just a single package (e.g. "hazelcast-antora-helpers") to simplify things
// the scripts can be then imported like `const { checkOrphanLinks } = require('hazelcast-antora-helpers');`

const fs = require('fs');
const path = require('path');

class NavLinksCollector {
static FILE_LINK_REGEXP = /xref:([\w,\s-]+:)?([\w,\s-]+.adoc)/;
static CHILD_NAV_REGEXP = /include::([\w,\s-]+):partial\$nav.adoc/;

// @TODO: use hashmap or dictionary to optimize
nav = [];

constructor(rootNavUrl) {
this.nav = this.readNavFile(rootNavUrl, 'ROOT');
}

/**
*
* @param filename - name of the .adoc file
* @param urlModule - the part of the URL in the nav file before filename. It can be a module name or blank.
* if it's blank, it means that antora builder will look up the page in twp places:
* in "ROOT" or in the current module
* @param navModule - the directory name of the current nav.adoc file
* @returns {String[]} - Strings with page URLs
*/
static buildFileUrl(filename, urlModule, navModule) {
const result = [];
if (urlModule) {
result.push(path.join('docs', 'modules', urlModule, 'pages', filename));
} else {
// check if there is no urlModule, then it means, that the page can either be in "ROOT" or in the current module
// that's why we are adding both possibilities to the list
if (navModule !== 'ROOT') {
result.push(path.join('docs', 'modules', 'ROOT', 'pages', filename));
}
result.push(path.join('docs', 'modules', navModule, 'pages', filename));
}
return result;
}

static buildChildNavUrl( navModule) {
// check if module is NULL, then use navModule instead
return `./docs/modules/${navModule}/partials/nav.adoc`;
}

readNavFile(url, navModule) {
const nav = [];
try {
const lines = fs.readFileSync(url, 'utf-8').split('\n');

for (const line of lines) {
const match = line.match(NavLinksCollector.FILE_LINK_REGEXP);
if (match) {
const filename = match[2];
// trim the ending ":"
const fileModule = match[1]?.slice(0, -1);
nav.push(...NavLinksCollector.buildFileUrl(filename, fileModule, navModule));
} else if (NavLinksCollector.CHILD_NAV_REGEXP.test(line)) {
const match = line.match(NavLinksCollector.CHILD_NAV_REGEXP);
const childNavModule = match[1];
const childNav = this.readNavFile(NavLinksCollector.buildChildNavUrl(childNavModule), childNavModule);
nav.push(...childNav);
}
}

} catch (err) {
console.error(err);
}
return nav;
}
}

function iteratePageFiles(navPages) {
const orphanPages = [];
const rootDir = path.join('docs', 'modules');
fs.readdirSync(rootDir).forEach((moduleDir) => {
const moduleUrl = path.join(rootDir, moduleDir);
if (fs.statSync(moduleUrl).isDirectory()) {
fs.readdirSync(path.join(moduleUrl, 'pages')).forEach((file) => {
const fileUrl = path.join(moduleUrl, 'pages', file);
if (!navPages.includes(fileUrl)) {
orphanPages.push(fileUrl);
}
});
}
});
return orphanPages;
}

function main() {
// 1. Parse nav files and create a depth-first-traversal array of the page file links
const linksCollector = new NavLinksCollector('./docs/modules/ROOT/nav.adoc');
// 2. Iterate recursively over all {module}/pages and lookup it in the navigation tree
const orphanPages = iteratePageFiles(linksCollector.nav);

if (orphanPages.length === 0) {
console.log('No orphan pages detected. YAY!');
} else {
console.warn('The following orphan pages were detected:');
console.warn(orphanPages);
}
}

main();
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"scripts": {
"build": "antora --to-dir docs --fetch antora-playbook.yml",
"build-local": "antora --to-dir test --fetch antora-playbook-local.yml",
"check-orphan-pages": "node orphan-pages-checker.js",
"serve": "serve test",
"expose": "ngrok http 5000"
},
Expand Down
Loading