Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
cb22f1f
Compile partial HTML for embedding into Bump API docs
JakeSCahill May 27, 2025
f36ce02
Quiet logs
JakeSCahill May 27, 2025
edef5c4
📝 Add docstrings to `bump-partials` (#296)
coderabbitai[bot] May 27, 2025
4609039
Fix inconsistency
JakeSCahill May 27, 2025
d9fe861
Merge branch 'bump-partials' of https://github.com/redpanda-data/docs…
JakeSCahill May 27, 2025
89a2e93
Support prereleases (#297)
JakeSCahill May 29, 2025
216a6c4
Bump
JakeSCahill May 30, 2025
21dc031
Update Bump
JakeSCahill Jun 4, 2025
5cf84a5
Update compile-partial.js
JakeSCahill Jun 4, 2025
f9c64ab
Remove static
JakeSCahill Jun 4, 2025
3a4f473
Merge branch 'bump-partials' of https://github.com/redpanda-data/docs…
JakeSCahill Jun 4, 2025
bcc62df
Add styles
JakeSCahill Jun 4, 2025
aad147a
Add styles
JakeSCahill Jun 4, 2025
6cc84f5
Update engine
JakeSCahill Jun 4, 2025
26713ee
Update node
JakeSCahill Jun 4, 2025
c65e8c5
Fix css
JakeSCahill Jun 4, 2025
8b76baf
Avoid prism
JakeSCahill Jun 4, 2025
9f1346c
Merge branch 'main' into bump-partials
JakeSCahill Jun 4, 2025
1a96589
Mobile header
JakeSCahill Jun 4, 2025
173e84a
Merge branch 'bump-partials' of https://github.com/redpanda-data/docs…
JakeSCahill Jun 4, 2025
81e9470
No dark mode header
JakeSCahill Jun 4, 2025
427ded3
Fix linter
JakeSCahill Jun 4, 2025
6dfb07e
Update order
JakeSCahill Jun 4, 2025
8364903
edits
JakeSCahill Jun 5, 2025
27dcc44
don't load site.js
JakeSCahill Jun 5, 2025
4c65323
fix scripts
JakeSCahill Jun 5, 2025
e07074e
Continue supporting Rapidoc for now
JakeSCahill Jun 6, 2025
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
4 changes: 2 additions & 2 deletions .github/workflows/publish-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
TAG="${{ github.ref_name }}"
ASSET=./build/ui-bundle.zip
FLAGS="--generate-notes"
if [[ "$TAG" == *-* ]]; then
FLAGS="$FLAGS --prerelease"
if [[ "$TAG" =~ - ]]; then
FLAGS+=" --prerelease"
fi
gh release create "$TAG" $ASSET $FLAGS

Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
/node_modules/
/public/
.DS_Store
blobl.wasm
blobl.wasm
/src/static
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
10
16
135 changes: 135 additions & 0 deletions compile-partial.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
const fs = require('fs');
const path = require('path');
const Handlebars = require('handlebars');

const helpersDir = path.join(__dirname, 'src', 'helpers');
if (fs.existsSync(helpersDir)) {
fs.readdirSync(helpersDir).forEach((file) => {
if (file.endsWith('.js')) {
const name = path.basename(file, '.js');
const helperFn = require(path.join(helpersDir, file));
if (typeof helperFn !== 'function') {
console.warn(`⚠️ Skipping ${file}: not a function`);
return;
}
Handlebars.registerHelper(name, helperFn);
}
});
}

function readJson(filepath) {
try {
return JSON.parse(fs.readFileSync(filepath, 'utf8'));
} catch (err) {
console.warn(`⚠️ Failed to read context JSON (${filepath}), using empty context.`);
return {};
}
}

// Parse args
const args = process.argv.slice(2);
const [partialName, jsonPathOrFlag, ...rest] = args;

if (!partialName) {
console.error('❌ Usage: node compile-partial.js <partial-name> [context.json] [--jsScripts=\'["a.js"]\']');
process.exit(1);
}

// Flags
let jsonPath = null;
let jsScripts = [];

for (const arg of [jsonPathOrFlag, ...rest]) {
if (arg?.startsWith('--jsScripts=')) {
try {
jsScripts = JSON.parse(arg.split('=')[1]);
} catch {
console.warn('⚠️ Invalid --jsScripts argument. Skipping.');
}
} else if (arg && !arg.startsWith('--')) {
jsonPath = arg;
}
}

// Paths
const baseDir = __dirname;
const partialsDir = path.join(baseDir, 'src', 'partials');
const cssSrcDir = path.join(baseDir, 'src', 'css');
const jsSrcDir = path.join(baseDir, 'src', 'js');
const outDir = path.join(baseDir, 'src', 'static', 'assets', 'widgets');
const cssOutDir = path.join(outDir, 'css');
const jsOutDir = path.join(outDir, 'js');

// Load partial template
const templatePath = path.join(partialsDir, `${partialName}.hbs`);
if (!fs.existsSync(templatePath)) {
console.error(`❌ Partial not found: ${templatePath}`);
process.exit(1);
}

// Register all partials
fs.readdirSync(partialsDir).forEach((file) => {
if (file.endsWith('.hbs')) {
const name = path.basename(file, '.hbs');
const template = fs.readFileSync(path.join(partialsDir, file), 'utf8');
Handlebars.registerPartial(name, template);
}
});

const templateSrc = fs.readFileSync(templatePath, 'utf8');
const template = Handlebars.compile(templateSrc);
const context = jsonPath ? readJson(path.resolve(jsonPath)) : {};

let html = template(context);

// 🔽 Inject CSS if exists
const sharedCssFiles = ['typeface-inter-bump.css', 'header-bump.css', 'footer-bump.css'];
const allCssFiles = [...sharedCssFiles, `${partialName}-bump.css`];
const cssTags = [];

fs.mkdirSync(cssOutDir, { recursive: true });

allCssFiles.forEach(cssFile => {
const srcPath = path.join(cssSrcDir, cssFile);
const outPath = path.join(cssOutDir, cssFile);
if (fs.existsSync(srcPath)) {
fs.copyFileSync(srcPath, outPath);
cssTags.push(`<link rel="stylesheet" href="/assets/widgets/css/${cssFile}">`);
} else if (cssFile !== `${partialName}-bump.css`) {
console.warn(`⚠️ Shared CSS not found: ${cssFile}`);
}
});

if (partialName === 'head-scripts') {
// Prepend styles
if (cssTags.length) {
html = `${html}\n${cssTags.join('\n')}`;
}
}

// 🔽 Inject JS scripts
if (Array.isArray(jsScripts)) {
fs.mkdirSync(jsOutDir, { recursive: true });

const scriptTags = jsScripts.map((jsFile) => {
const jsSrcPath = path.join(jsSrcDir, jsFile);
const jsOutPath = path.join(jsOutDir, jsFile);

if (fs.existsSync(jsSrcPath)) {
fs.copyFileSync(jsSrcPath, jsOutPath);
return `<script src="/assets/widgets/js/${jsFile}"></script>`;
} else {
console.warn(`⚠️ JS script not found: ${jsSrcPath}`);
return '';
}
}).filter(Boolean).join('\n ');

if (scriptTags) {
html = `${html}\n${scriptTags}`;
}
}

// Output HTML
fs.mkdirSync(outDir, { recursive: true });
const outFile = path.join(outDir, `${partialName}.html`);
fs.writeFileSync(outFile, html);
5 changes: 5 additions & 0 deletions context/footer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"isStandaloneWidget": "true",
"includeAlgoliaScript": "true",
"uiRootPath": "/_"
}
10 changes: 10 additions & 0 deletions context/head.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"site": {
"keys": {
"googleAnalytics": "GTM-WB2CSV5"
}
},
"isStandaloneWidget": "true",
"includeAlgoliaScript": "true",
"uiRootPath": "/_"
}
85 changes: 85 additions & 0 deletions context/header.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
{
"isStandaloneWidget": "true",
"includeAlgoliaScript": "true",
"site": {
"keys": {
"googleAnalytics": "GTM-WB2CSV5"
},
"homeUrl": "/",
"components": {
"redpanda-labs": {
"latest": {
"title": "Labs",
"url": "/redpanda-labs/",
"asciidoc": {
"attributes": {
"page-header-data": {
"order": 4
}
}
}
}
},
"api": {
"latest": {
"title": "API",
"url": "/api/"
}
},
"redpanda-cloud": {
"latest": {
"title": "Cloud",
"url": "/redpanda-cloud/home/",
"asciidoc": {
"attributes": {
"page-header-data": {
"order": 1 }
}
}
}
},
"redpanda-connect": {
"latest": {
"title": "Connect",
"url": "/redpanda-connect/home/",
"asciidoc": {
"attributes": {
"page-header-data": {
"order": 3
}
}
}
}
},
"ROOT": {
"latest": {
"title": "Self-Managed",
"url": "/current/home/",
"asciidoc": {
"attributes": {
"page-header-data": {
"order": 2
}
}
}
}
}
}
},
"page": {
"component": {
"title": "API",
"latest": {
"asciidoc": {
"attributes": {
"page-header-data": {
"color": "#d73d23"
}
}
}
}
}
},
"uiRootPath": "/_"
}

36 changes: 34 additions & 2 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const { parallel, series, watch } = require('gulp')
const createTask = require('./gulp.d/lib/create-task')
const exportTasks = require('./gulp.d/lib/export-tasks')
const log = require('fancy-log')
const { exec } = require('child_process')
const { exec, execSync } = require('child_process')
const path = require('path')
const gulp = require('gulp')

Expand All @@ -28,6 +28,38 @@ const glob = {
const rapidocSrc = 'node_modules/rapidoc/dist/rapidoc-min.js'
const rapidocDest = path.join(srcDir, 'static')

/**
* Compiles Handlebars partial templates by executing a Node.js script for each specified partial.
*
* @param {Function} cb - Callback to signal task completion or failure.
*
* @throws {Error} If any partial compilation fails, the callback is invoked with an error.
*/
function compileWidgets (cb) {
const partialsToCompile = [
{ name: 'header', context: 'context/header.json' },
{ name: 'footer', context: 'context/footer.json', scripts: ['05-mobile-navbar.js'] },
{ name: 'head-scripts', context: 'context/head.json' },
]

try {
for (const { name, context, scripts } of partialsToCompile) {
const jsArg = scripts ? ` --jsScripts='${JSON.stringify(scripts)}'` : ''
const ctxArg = context ? `${context}` : ''
const cmd = `node compile-partial.js ${name} ${ctxArg}${jsArg}`.trim()
execSync(cmd, { stdio: 'inherit' })
}
cb()
} catch (err) {
cb(new Error(`Failed to compile Handlebars partials: ${err.message}`))
}
}

/**
* Copies the Rapidoc JavaScript file from the source location to the static assets directory.
*
* @returns {Stream} A Gulp stream representing the copy operation.
*/
function copyRapidoc () {
return gulp.src(rapidocSrc)
.pipe(gulp.dest(rapidocDest))
Expand Down Expand Up @@ -103,7 +135,7 @@ const buildWasmTask = createTask({

const bundleBuildTask = createTask({
name: 'bundle:build',
call: series(cleanTask, lintTask, buildWasmTask, copyRapidoc, buildTask),
call: series(cleanTask, lintTask, buildWasmTask, copyRapidoc, compileWidgets, buildTask),
})

const bundlePackTask = createTask({
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"url": "https://github.com/redpanda-data/docs-ui.git"
},
"engines": {
"node": ">= 14.0.0"
"node": ">= 16.0.0"
},
"browserslist": [
"last 2 versions"
Expand Down
1 change: 1 addition & 0 deletions src/css/dark-mode.css
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ html[data-theme=dark] {
--toolbar-background: var(--body-background);
--toolbar-border-color: var(--panel-border-color);
--toolbar-font-color: var(--body-font-color);
--default-header-color: var(--redpanda-800);
--toolbar-muted-color: var(--color-gray-40);
--page-version-menu-background: #545454;
--page-version-font-color: var(--body-font-color);
Expand Down
Loading
Loading