Skip to content

Commit

Permalink
Support Browser History in ClaroDocs Generated Site
Browse files Browse the repository at this point in the history
This was a fairly straightforward change that stores state in URL query params instead of using React's `useState()` directly since now when the site auto-reloads, it'll reload to the specific URL that it was at before the reload and so you won't get disrupted in your browsing of the site just because you made a code change. There're probably some weird edge cases here where you'd need to manually navigate back to the DepGraph (home) if the query params are invalid, but that's fine. Arguably, this should now be in a good enough state to actually push a release to the BCR with this.
  • Loading branch information
JasonSteving99 committed Mar 31, 2024
1 parent 0cc52fa commit c58590b
Show file tree
Hide file tree
Showing 20 changed files with 162 additions and 78 deletions.
2 changes: 1 addition & 1 deletion MODULE.bazel
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module(
name = "claro-lang",
repo_name = "claro-lang",
version = "0.1.409",
version = "0.1.499",
)

bazel_dep(name = "aspect_bazel_lib", version = "2.0.1")
Expand Down
2 changes: 2 additions & 0 deletions logo/BUILD
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
load("@aspect_rules_js//js:defs.bzl", "js_library")

exports_files([
"ClaroLogoFromArrivalHeptapodOfferWeapon1.jpeg",
"ClaroLogoFromArrivalHeptapodOfferWeapon-transparentBackground.png",
Expand Down
6 changes: 3 additions & 3 deletions tools/clarodocs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="/favicon.ico" />
<link rel="icon" href="/claro-logo.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="theme-color" content="#FFFFFF" />
<meta
name="description"
content="Web site created using create-react-app"
Expand All @@ -15,7 +15,7 @@
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="/manifest.json" />
<title>React App</title>
<title>ClaroDocs</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
Expand Down
1 change: 1 addition & 0 deletions tools/clarodocs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"mermaid": "10.8.0",
"react": "~18.2.0",
"react-dom": "~18.2.0",
"react-router-dom": "^6.22.3",
"web-vitals": "2.1.4"
},
"devDependencies": {
Expand Down
31 changes: 31 additions & 0 deletions tools/clarodocs/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file added tools/clarodocs/public/claro-logo-192x192.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tools/clarodocs/public/claro-logo-512x512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added tools/clarodocs/public/claro-logo.ico
Binary file not shown.
Binary file removed tools/clarodocs/public/favicon.ico
Binary file not shown.
Binary file removed tools/clarodocs/public/logo192.png
Binary file not shown.
Binary file removed tools/clarodocs/public/logo512.png
Binary file not shown.
12 changes: 6 additions & 6 deletions tools/clarodocs/public/manifest.json
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"short_name": "ClaroDocs",
"name": "ClaroDocs",
"icons": [
{
"src": "favicon.ico",
"src": "claro-logo.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"src": "claro-logo-192x192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"src": "claro-logo-512x512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"theme_color":"#ffffff",
"background_color": "#ffffff"
}
85 changes: 69 additions & 16 deletions tools/clarodocs/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,53 @@ import { HighlightJS } from './components/highlight_js/HighlightJS';
import { DepGraph } from './components/dep_graph/DepGraph';
import { WholeProgramDepGraph } from './components/dep_graph/WholeProgramDepGraph';
import { ModuleTree } from './components/module_tree/ModuleTree';
import {
createBrowserRouter,
RouterProvider,
useSearchParams
} from "react-router-dom";
// import { useSearchParamsState } from './hooks/UseSearchParamsHook';

import { Breadcrumb, ConfigProvider, Layout, Menu, theme } from 'antd';
const { Header, Sider, Content } = Layout;

function App() {
const [showDepGraph, setShowDepGraph] = useState(true);
const {
token: { colorBgContainer, borderRadiusLG },
} = theme.useToken();

const [ selectedModule, setSelectedModule ] = useState('');
const [ targetType, setTargetType ] = useState('');
function AppImpl() {
const [ searchParams, setSearchParams ] = useSearchParams();

const [ ClaroModules, rootName, rootDeps ] = getClaroModules(setSelectedModule);
const showDepGraph = searchParams.get('showDepGraph') === null || searchParams.get('showDepGraph') === 'true';
let selectedModule = searchParams.get('selectedModule') || '';
const targetType = searchParams.get('targetType') || '';

// We'll reuse these tooltip components every time the dep is referenced in the Module API.
const selectedModuleDepsTooltips = ClaroModules[selectedModule]?.deps;
const setShowDepGraph = function() {
setSearchParams({
showDepGraph: !showDepGraph,
selectedModule: '',
targetType: ''
});
}
const setSelectedModule = function(newSelectedModule) {
setSearchParams({
showDepGraph: false,
selectedModule: newSelectedModule,
targetType: targetType
});
}
const setSelectedModuleAndTargetType = function(newSelectedModule, newTargetType) {
setSearchParams({
showDepGraph: false,
selectedModule: newSelectedModule,
targetType: newTargetType
});
}
const setTargetType = function(newTargetType) {
setSearchParams({
showDepGraph: showDepGraph,
selectedModule: selectedModule,
targetType: newTargetType
});
}

const [ ClaroModules, rootName, rootDeps ] = getClaroModules(setSelectedModule);

useEffect(
() => {
Expand All @@ -42,6 +71,19 @@ function App() {
);

function APIs() {
if (!selectedModule) {
// Ensure that this still works even if the user just clicked the APIs tab directly without manually selecting a
// module.
selectedModule = Object.keys(ClaroModules).toSorted()[0];
}

// We'll reuse these tooltip components every time the dep is referenced in the Module API.
const selectedModuleDepsTooltips = ClaroModules[selectedModule]?.deps;

const {
token: { colorBgContainer, borderRadiusLG },
} = theme.useToken();

return (
<Layout hasSider>
<React.StrictMode>
Expand Down Expand Up @@ -131,9 +173,8 @@ function App() {
className="claro"
style={{ textAlign: "left" }}
id={selectedModule}
setSelectedModule={setSelectedModule}
targetType={targetType}
setTargetType={setTargetType}
setSelectedMOduleAndTargetType={setSelectedModuleAndTargetType}
selectedModuleDepsTooltips={selectedModuleDepsTooltips}
>
{ClaroModules[selectedModule]?.api}
Expand All @@ -152,7 +193,6 @@ function App() {
modules={ClaroModules}
selectedModule={selectedModule}
setSelectedModule={setSelectedModule}
setShowDepGraph={setShowDepGraph}
/>
);
}
Expand All @@ -170,14 +210,14 @@ function App() {
return (
<div className="App" style={{ display: "flex", width: "100vw" }}>
<Layout>
<Header style={{ display: 'flex', height: '8vh' }}>
<Header style={{ display: 'flex', height: '12vh' }}>
<div className="demo-logo" />
<Menu
theme="dark"
mode="horizontal"
selectedKeys={[showDepGraph ? 'Dep Graph' : 'APIs']}
items={headerNavItems}
onClick={({ key }) => setShowDepGraph(!showDepGraph)}
onClick={({ key }) => setShowDepGraph()}
style={{ flex: 1, minWidth: 200 }}
/>
</Header>
Expand All @@ -189,4 +229,17 @@ function App() {
);
}

function App() {
// We'll wrap everything in a React Router literally just so that it can easily maintain state from query params.
// The useSearchParams() function simply doesn't work outside of this RouterProvider context. Lame.
const router = createBrowserRouter([
{
path: "/",
element: <AppImpl />,
},
]);

return <RouterProvider router={router} />
}

export default App;
1 change: 1 addition & 0 deletions tools/clarodocs/src/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ ts_project(
"//tools/clarodocs/src/components/input",
"//tools/clarodocs/src/components/module_tree",
"//tools/clarodocs/src/claro_module_apis",
"//tools/clarodocs/src/hooks:use_search_params_hook",
],
)

Expand Down
2 changes: 1 addition & 1 deletion tools/clarodocs/src/claro_module_apis/demo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function getClaroModules(setSelectedModule) {
// Copy the data so that it's not overwritten.
const fmtMod = formatUniqueModuleName(mod);
claroModules[fmtMod] = {};
claroModules[fmtMod]['api'] = data.depGraph[mod].api;
claroModules[fmtMod]['api'] = data.depGraph[mod].api.trim();
claroModules[fmtMod]['deps'] = {};

for (let dep of Object.keys(data.depGraph[mod].deps)) {
Expand Down
44 changes: 0 additions & 44 deletions tools/clarodocs/src/claro_module_apis/testjson.json

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Mermaid } from '../mermaid/Mermaid';

export function WholeProgramDepGraph({ rootName, rootDeps, modules, selectedModule, setSelectedModule, setShowDepGraph }) {
export function WholeProgramDepGraph({ rootName, rootDeps, modules, selectedModule, setSelectedModule}) {
let mermaidGraph = 'graph LR;\n';

for (let rootDep of Object.keys(rootDeps).toSorted()) {
Expand All @@ -24,8 +24,7 @@ export function WholeProgramDepGraph({ rootName, rootDeps, modules, selectedModu
}
// Every node navigates to its Module API page.
nodeOnClickCallbacks[module[0]] = () => {
setSelectedModule(module[0]);
setShowDepGraph(false); // Navigate to the API.
setSelectedModule(module[0]); // Navigate to the API.
}
}

Expand Down
6 changes: 2 additions & 4 deletions tools/clarodocs/src/components/highlight_js/HighlightJS.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ export class HighlightJS extends React.Component {
const nextNode = codeEl.childNodes[i + 1];
if (this.isExpectedSpan(nextNode, '::')) {
// Make sure that `this` doesn't escape the current scope.
const setSelectedModule = this.props.setSelectedModule;
const setTargetType = this.props.setTargetType;
const setSelectedMOduleAndTargetType = this.props.setSelectedMOduleAndTargetType;

const depName = el.textContent.trim();
const targetType = codeEl.childNodes[i + 2].textContent.trim();
Expand All @@ -62,8 +61,7 @@ export class HighlightJS extends React.Component {

const _selectedModule = this.props.selectedModuleDepsTooltips[depName].path;
function _setSelectedModule(e) {
setSelectedModule(_selectedModule);
setTargetType(targetType);
setSelectedMOduleAndTargetType(_selectedModule, targetType);
}
// First replace the dep reference with its tooltip
const newTargetTypeNode = document.createElement('span');
Expand Down
15 changes: 15 additions & 0 deletions tools/clarodocs/src/hooks/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
load("@aspect_rules_ts//ts:defs.bzl", "ts_project")
load("//tools/clarodocs:defs.bzl", "TRANSPILER")

ts_project(
name = "use_search_params_hook",
srcs = ["UseSearchParamsHook.tsx"],
declaration = True,
resolve_json_module = True,
transpiler = TRANSPILER,
tsconfig = "//tools/clarodocs:tsconfig",
visibility = ["//tools/clarodocs:__subpackages__"],
deps = [
"//tools/clarodocs:node_modules/react-router-dom",
],
)
Loading

0 comments on commit c58590b

Please sign in to comment.