Skip to content
Open
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
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"name": "keploy-docs",
"version": "0.0.0",
"private": true,

"scripts": {
"docusaurus": "docusaurus",
"start": "docusaurus start",
Expand Down
6 changes: 6 additions & 0 deletions plugins/docusaurus-tailwindcss-loader/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "docusaurus-tailwindcss-loader",
"version": "1.0.0",
"main": "index.js",
"private": true
}
31 changes: 31 additions & 0 deletions scripts/find_invalid_versions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
const fs = require('fs');
const path = require('path');
function readJSON(p){ try{ return JSON.parse(fs.readFileSync(p,'utf8')); }catch(e){ return null; }}
const root = process.cwd();
console.log('Scanning package.json...');
const pkg = readJSON(path.join(root,'package.json'));
if(!pkg){ console.error('Could not read root package.json'); process.exit(2); }
const deps = {...pkg.dependencies, ...pkg.devDependencies};
let found = false;
for(const [k,v] of Object.entries(deps)){
if(typeof v !== 'string' || v.trim() === ''){
console.log('BAD_DEP_VERSION', k, JSON.stringify(v)); found = true;
}
}
console.log('Scanning plugins for package.json files...');
const pluginsDir = path.join(root,'plugins');
if(fs.existsSync(pluginsDir)){
for(const name of fs.readdirSync(pluginsDir)){
const p = path.join(pluginsDir,name,'package.json');
if(fs.existsSync(p)){
const sub = readJSON(p);
if(!sub || !sub.version || sub.version.trim()===''){
console.log('BAD_PLUGIN_VERSION', name, p, sub && sub.version);
found = true;
}
} else {
// plugins may not have package.json which is fine
}
}
}
if(!found) console.log('No obvious empty or non-string versions found.');
53 changes: 53 additions & 0 deletions src/components/LogViewer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React, {useState, useMemo} from 'react';
import styles from './LogViewer.module.css';

// Minimal responsive log viewer component
export default function LogViewer({logs = []}) {
const [query, setQuery] = useState('');
const [level, setLevel] = useState('all');

const levels = ['all','error','warn','info','debug'];

const filtered = useMemo(()=>{
const q = query.trim().toLowerCase();
return logs.filter(l=> (level==='all' || l.level===level) && (!q || l.message.toLowerCase().includes(q) || (l.meta && JSON.stringify(l.meta).toLowerCase().includes(q))));
},[logs, query, level]);

return (
<div className={`container ${styles.wrapper}`} aria-live="polite">
<header className={styles.header}>
<div className={styles.controls}>
<label className={styles.searchLabel}>
<span className={styles.visuallyHidden}>Filter logs</span>
<input aria-label="Filter logs" className={styles.search} value={query} onChange={e=>setQuery(e.target.value)} placeholder="Search logs..." />
</label>

<label className={styles.selectLabel}>
<span className={styles.visuallyHidden}>Log level</span>
<select aria-label="Log level" value={level} onChange={e=>setLevel(e.target.value)}>
{levels.map(l=> <option key={l} value={l}>{l}</option>)}
</select>
</label>
</div>
<div className={styles.count}>{filtered.length} entries</div>
</header>

<main className={styles.logPane}>
{filtered.length===0 ? (
<div className={styles.empty}>No log entries match your filters.</div>
) : (
<ol className={styles.list}>
{filtered.map((l,i)=> (
<li key={i} className={`${styles.line} ${styles[l.level] || ''}`}>
<time className={styles.time}>{l.time}</time>
<span className={styles.level}>{l.level.toUpperCase()}</span>
<span className={styles.msg}>{l.message}</span>
{l.meta && <pre className={styles.meta}>{JSON.stringify(l.meta,null,2)}</pre>}
</li>
))}
</ol>
)}
</main>
</div>
);
}
38 changes: 38 additions & 0 deletions src/components/LogViewer.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
.wrapper {
margin: 1rem 0 2rem;
}
.header {
display:flex;
flex-wrap:wrap;
align-items:center;
gap:0.5rem 1rem;
justify-content:space-between;
margin-bottom:0.5rem;
}
.controls{ display:flex; gap:0.5rem; align-items:center; }
.search { padding:0.5rem .65rem; border-radius:6px; border:1px solid #ddd; min-width:180px; }
.selectLabel select { padding:0.45rem .5rem; border-radius:6px; border:1px solid #ddd; }
.count { color:var(--ifm-color-emphasis-300); }
.logPane { background:var(--ifm-card-background-color); border-radius:8px; padding:0.5rem; box-shadow:0 6px 15px rgba(0,0,0,0.04); max-height:50vh; overflow:auto; }
.list { list-style:none; margin:0; padding:0; }
.line { display:block; padding:.5rem .75rem; border-bottom:1px solid rgba(0,0,0,0.03); font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, 'Roboto Mono', 'Courier New', monospace; font-size:0.95rem; }
.time { color: #777; margin-right:0.75rem; font-size:0.85rem; }
.level { font-weight:700; margin-right:0.6rem; text-transform:uppercase; font-size:0.75rem; padding:.15rem .4rem;border-radius:4px; }
.msg { color:var(--ifm-color); }
.meta { background: rgba(0,0,0,0.03); padding: .5rem; border-radius:6px; margin-top:0.5rem; overflow:auto; }
.empty { padding:1rem; color:var(--ifm-color-emphasis-300); }

/* severity colours */
.error .level { background:#ffe6e6; color:#b91c1c; }
.warn .level { background:#fff4e6; color:#b45309; }
.info .level { background:#e8f3ff; color:#0366d6; }
.debug .level { background:#eef2ff; color:#4338ca; }

/* responsive tweaks */
@media (max-width: 640px){
.header { gap:0.5rem; }
.search { min-width:120px; }
.line { font-size:0.9rem; }
}

.visuallyHidden { position:absolute !important; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0; }
87 changes: 87 additions & 0 deletions src/css/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,93 @@ footer svg {

/* Docs */

/* Responsive helpers and utilities
- container, grid, responsive images, type scaling
- accessible focus, reduced-motion support
Usage: wrap content with `.container` or use `.grid` for responsive columns.
*/
:root {
--bp-sm: 640px;
--bp-md: 768px;
--bp-lg: 1024px;
--bp-xl: 1280px;
--container-max: 1200px;
--container-padding: 1rem;
}

.container {
width: 100%;
max-width: var(--container-max);
padding-left: var(--container-padding);
padding-right: var(--container-padding);
margin-left: auto;
margin-right: auto;
box-sizing: border-box;
}

.grid {
display: grid;
gap: 1rem;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}

.img-responsive, img.responsive {
max-width: 100%;
height: auto;
display: block;
}

.lead {
font-size: 1.125rem;
line-height: 1.6;
}

.visually-hidden {
position: absolute !important;
width: 1px; height: 1px;
padding: 0; margin: -1px;
overflow: hidden; clip: rect(0 0 0 0);
white-space: nowrap; border: 0;
}

/* Simple two-column layout utility */
.two-cols {
display: grid;
gap: 1rem;
grid-template-columns: 1fr;
}
@media (min-width: var(--bp-md)) {
.two-cols { grid-template-columns: 1fr 1fr; }
}

/* Heading responsive scaling */
h1 { font-size: clamp(1.45rem, 2.5vw + 0.5rem, 2.5rem); }
h2 { font-size: clamp(1.25rem, 2vw + 0.4rem, 1.75rem); }

/* Focus visible for keyboard users */
:focus-visible {
outline: 3px solid var(--ifm-color-primary);
outline-offset: 2px;
}

/* Respect users who prefer reduced motion */
@media (prefers-reduced-motion: reduce) {
* { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; scroll-behavior: auto !important; }
}

/* Small usage example (HTML)
<div class="container">
<header class="two-cols">
<div>Brand / Title</div>
<nav>Navigation</nav>
</header>
<main class="grid">
<article class="lead">Your main content</article>
<aside>Sidebar content (stacked on small screens)</aside>
</main>
</div>
*/

.docusaurus-highlight-code-line {
background-color: rgb(72, 77, 91);
display: block;
Expand Down
26 changes: 26 additions & 0 deletions src/pages/logs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react';
import LogViewer from '../components/LogViewer';

const sampleLogs = [
{time:'2025-12-16 10:00:01', level:'info', message:'Server started on http://localhost:3000'},
{time:'2025-12-16 10:01:10', level:'warn', message:'Cache miss for key user:42'},
{time:'2025-12-16 10:02:45', level:'error', message:'Unhandled exception in worker', meta:{err:'TypeError', trace:['file.js:42'] }},
{time:'2025-12-16 10:03:07', level:'debug', message:'Request headers: {"user-agent":"curl/7"}'},
];

export default function LogsPage(){
return (
<main className="container">
<h1>Log Viewer</h1>
<p className="lead">A responsive log viewer component with filtering and accessible controls.</p>
<LogViewer logs={sampleLogs} />

<section>
<h2>Usage</h2>
<pre>
{`<LogViewer logs={[{time:'...', level:'info', message:'...'}]} />`}
</pre>
</section>
</main>
);
}