Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 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
2 changes: 1 addition & 1 deletion .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@
{
"label": "VSCode: Watch tutorial",
"type": "npm",
"script": "watch:tailwind",
"script": "watch",
"isBackground": true,
"presentation": {
"reveal": "never"
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@
"eslint-plugin-unicorn": "^63.0.0",
"eslint-plugin-unused-imports": "^4.4.1",
"prettier": "^3.8.1",
"prettier-plugin-tailwindcss": "^0.7.2",
"syncpack": "^14.2.0",
"tsx": "^4.21.0",
"typescript": "^5.9.3",
Expand Down
16 changes: 5 additions & 11 deletions packages/cheatsheet-local/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,36 +13,30 @@
"default": "./out/index.js"
}
},
"postcss": {
"plugins": {
"@tailwindcss/postcss": {}
}
},
"scripts": {
"test": "jest",
"compile": "tsc --build",
"watch": "tsc --build --watch",
"build": "pnpm build:prod",
"serve": "vite serve",
"preview": "vite preview",
"build": "vite build",
"build:dev": "vite build --mode development",
Comment thread
AndreasArvidsson marked this conversation as resolved.
"build:prod": "vite build --mode production",
"clean": "rm -rf ./out tsconfig.tsbuildinfo ./dist ./build"
},
"dependencies": {
"@cursorless/cheatsheet": "workspace:*",
"@cursorless/common": "workspace:*",
"bootstrap": "^5.3.8",
"preact": "^10.29.0",
"tslib": "^2.8.1"
},
"devDependencies": {
"@preact/preset-vite": "^2.10.3",
"@tailwindcss/postcss": "^4.2.1",
"@types/jest": "^30.0.0",
"@types/node": "^24.12.0",
"jest": "^30.3.0",
"postcss": "^8.5.8",
"tailwindcss": "^4.2.1",
"typescript": "^5.9.3",
"vite": "^8.0.0",
"vite-plugin-purgecss": "^0.2.13",
"vite-plugin-singlefile": "^2.3.0"
}
}
1 change: 0 additions & 1 deletion packages/cheatsheet-local/src/app/app.module.scss

This file was deleted.

4 changes: 2 additions & 2 deletions packages/cheatsheet-local/src/app/app.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { CheatsheetInfo } from "@cursorless/cheatsheet";
import { CheatsheetPage } from "@cursorless/cheatsheet";
import { Cheatsheet } from "@cursorless/cheatsheet";
import "./styles.css";

Comment thread
AndreasArvidsson marked this conversation as resolved.
declare global {
Expand All @@ -16,5 +16,5 @@ declare global {
}

export function App() {
return <CheatsheetPage cheatsheetInfo={document.cheatsheetInfo} />;
return <Cheatsheet cheatsheetInfo={document.cheatsheetInfo} />;
}
4 changes: 1 addition & 3 deletions packages/cheatsheet-local/src/app/styles.css
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
@import "tailwindcss";

@config "../../tailwind.config.mjs";
@import "bootstrap/dist/css/bootstrap.min.css";
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { fakeCheatsheetInfo } from "@cursorless/cheatsheet";
import { render } from "preact";
import { act } from "preact/test-utils";
import { App } from "./app";
import { App } from "../app/app";

describe("App", () => {
beforeEach(() => {
Expand Down
17 changes: 0 additions & 17 deletions packages/cheatsheet-local/tailwind.config.mjs

This file was deleted.

16 changes: 10 additions & 6 deletions packages/cheatsheet-local/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
import { fakeCheatsheetInfo } from "@cursorless/cheatsheet";
import { defaultCheatsheetInfo } from "@cursorless/cheatsheet";
import { viteHtmlParams } from "@cursorless/common";
import preact from "@preact/preset-vite";
import { defineConfig } from "vite";
import { defineConfig, type UserConfig } from "vite";
import purgeCss from "vite-plugin-purgecss";
import { viteSingleFile } from "vite-plugin-singlefile";

export default defineConfig(() => {
export default defineConfig((): UserConfig => {
return {
build: {
outDir: "dist",
},

resolve: {
conditions: ["cursorless:bundler"],
},

plugins: [
preact(),
purgeCss({}),
Comment thread
AndreasArvidsson marked this conversation as resolved.
viteSingleFile(),
viteHtmlParams({
FAKE_CHEATSHEET_INFO: JSON.stringify(fakeCheatsheetInfo),
FAKE_CHEATSHEET_INFO: JSON.stringify(defaultCheatsheetInfo),
}),
],
};
Expand Down
5 changes: 4 additions & 1 deletion packages/cheatsheet/jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import { preactModuleNameMapper } from "@cursorless/common";
const config: Config = {
preset: "ts-jest",
testEnvironment: "jsdom",
moduleNameMapper: preactModuleNameMapper,
moduleNameMapper: {
...preactModuleNameMapper,
"\\.(css|scss)$": "<rootDir>/src/test/styleMock.ts",
},
};

export default config;
6 changes: 3 additions & 3 deletions packages/cheatsheet/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export * from "./lib/CheatsheetPage";
export * from "./lib/CheatsheetInfo";
export * from "./lib/fakeCheatsheetInfo";
export * from "./lib/Cheatsheet";
export * from "./lib/cheatsheet.types";
export * from "./lib/utils/fakeCheatsheetInfo";
export { default as defaultCheatsheetInfo } from "./lib/sampleSpokenFormInfos/defaults.json";
64 changes: 64 additions & 0 deletions packages/cheatsheet/src/lib/Cheatsheet.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { faCircleQuestion } from "@fortawesome/free-solid-svg-icons/faCircleQuestion";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useEffect } from "preact/hooks";
import "./cheatsheet.css";
import type { CheatsheetInfo } from "./cheatsheet.types";
import { cheatsheetLegendData } from "./utils/cheatsheetLegendData";
import CheatsheetLegendSection from "./CheatsheetLegendSection";
import CheatsheetListSection from "./CheatsheetListSection";
import CheatsheetNotesSection from "./CheatsheetNotesSection";
import { applyBootstrapTheme } from "./utils/applyBootstrapTheme";
import SmartLink from "./utils/SmartLink";

type Props = {
cheatsheetInfo: CheatsheetInfo;
};

export function Cheatsheet({ cheatsheetInfo }: Props) {
useEffect(() => {
return applyBootstrapTheme();
}, []);

return (
<main className="cheatsheet">
<div className="container-xxl pb-2">
<Title />
<CheatsheetSections cheatsheetInfo={cheatsheetInfo} />
</div>
</main>
);
}

function Title() {
return (
<div className="col-12 text-center mb-3">
<h1>
Cursorless Cheatsheet{" "}
<SmartLink to="#legend">
<FontAwesomeIcon icon={faCircleQuestion} className="question-icon" />
</SmartLink>
<small>
See the{" "}
<SmartLink to={"https://www.cursorless.org/docs/"}>
full documentation
</SmartLink>{" "}
to learn more.
</small>
</h1>
</div>
);
}

function CheatsheetSections({ cheatsheetInfo }: Props) {
return (
<div className="cheatsheet-sections">
{cheatsheetInfo.sections
.filter((section) => section.items.length > 0)
.map((section) => (
<CheatsheetListSection section={section} />
))}
<CheatsheetLegendSection data={cheatsheetLegendData} />
<CheatsheetNotesSection />
</div>
);
}
62 changes: 62 additions & 0 deletions packages/cheatsheet/src/lib/CheatsheetLegendSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import type { JSX } from "preact";
import type { CheatsheetLegend } from "./cheatsheet.types";
import { formatCaptures } from "./utils/formatCaptures";
import SmartLink from "./utils/SmartLink";
import useIsHighlighted from "./utils/useIsHighlighted";

type Props = {
data: CheatsheetLegend;
};

export default function CheatsheetLegendSection({ data }: Props): JSX.Element {
const isHighlighted = useIsHighlighted("legend");

return (
<section
id="legend"
className={"card bg-info" + (isHighlighted ? " highlighted" : "")}
>
<div className="card-header">
<h2>Legend</h2>
</div>
<div className="card-body">
<table className="table table-striped">
<thead>
<tr>
<th>Term</th>
<th>Definition</th>
</tr>
</thead>
<tbody>
{data.map(({ term, definition, link, linkName, id }) => (
<tr key={id}>
<td>{formatCaptures(`<${term}>`)}</td>
<td>{renderDefinition(definition, link, linkName)}</td>
</tr>
))}
</tbody>
</table>
</div>
</section>
);
}

function renderDefinition(
definition: string,
link?: string,
linkName?: string,
) {
if (link == null) {
return definition;
}
if (linkName == null) {
return <SmartLink to={link}>{definition}</SmartLink>;
}
return (
<>
<SmartLink to={link}>{linkName}</SmartLink>
&nbsp;
{definition}
</>
);
}
66 changes: 66 additions & 0 deletions packages/cheatsheet/src/lib/CheatsheetListSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import type { JSX } from "preact";
import type { CheatsheetSection, Variation } from "./cheatsheet.types";
import useIsHighlighted from "./utils/useIsHighlighted";
import { formatCaptures } from "./utils/formatCaptures";

type Props = {
section: CheatsheetSection;
};

export default function CheatsheetListSection({ section }: Props): JSX.Element {
const isHighlighted = useIsHighlighted(section.id);

const variations = section.items.flatMap((item) => item.variations);

variations.sort((form1, form2) =>
form1.spokenForm.localeCompare(form2.spokenForm),
);

return (
<section
id={section.id}
className={"card" + (isHighlighted ? " highlighted" : "")}
>
<div className="card-header">
<h2>{section.name}</h2>
</div>
<div className="card-body">
<table className="table table-striped">
<thead>
<tr>
<th>Spoken form</th>
<th>Meaning</th>
</tr>
</thead>
<tbody>
{variations.map((variation) => (
<CheatsheetListEntry
key={variation.spokenForm}
variation={variation}
/>
))}
</tbody>
</table>
</div>
</section>
);
}

type CheatsheetListEntryProps = {
variation: Variation;
};

function CheatsheetListEntry({
variation: { spokenForm, description },
}: CheatsheetListEntryProps): JSX.Element {
return (
<tr>
<td>
<span className="opening-quote">&#8220;</span>
{formatCaptures(spokenForm)}
<span className="closing-quote">&#8221;</span>
</td>
<td>{formatCaptures(description)}</td>
</tr>
);
}
14 changes: 14 additions & 0 deletions packages/cheatsheet/src/lib/CheatsheetNotesSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { JSX } from "preact";
import SmartLink from "./utils/SmartLink";

export default function CheatsheetNotesSection(): JSX.Element {
return (
<section id="notes" className="text-center">
See the{" "}
<SmartLink to={"https://www.cursorless.org/docs/"}>
full documentation
</SmartLink>{" "}
to learn more.
</section>
);
}
Loading
Loading