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
27 changes: 5 additions & 22 deletions docs/adding-languages.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Add an SVG logo into the `public/languages/` directory.
1. Import the type for the new language options from `src/hooks/use-explorer.ts`.
1. Add an entry in the `languages` variable for the new language.
1. Export a new variable describing the available modes for the new language (such as `jsonModes` or `cssModes`).
1. Default the default code for the new language (such as `defaultJsonCode` or `defaultCssCode`).
1. Define the default code for the new language (such as `defaultJsonCode` or `defaultCssCode`).
1. Add an entry in the `defaultCode` variable for the new language's default code.
1. Export a variable containing the default options for the new language (such as `defaultJsonOptions` or `defaultCssOptions`).
1. Add an entry to the `esquerySelectorPlaceholder` constant for the new language(must match Language enum), using an appropriate example selector.
Expand All @@ -32,32 +32,15 @@ Now import the default options for the new language from `src/lib/const.ts`.
## Step 5: Update `src/components/options.tsx`

1. Import the new language mode type from `src/hooks/use-explorer` (such as `JsonMode` or `CssMode`).
1. Import the available modes for the new language from `src/hooks/const` (such as `jsonModes` or `cssModes`).
1. Import the available modes for the new language from `src/lib/const.ts` (such as `jsonModes` or `cssModes`).
1. Create an options panel for the new language (such as `JsonPanel` or `CssPanel`).
1. Update the `Panel` variable to use the new options panel.

## Step 6: Update `src/components/editor.ts`
## Step 6: Update `src/components/editor.tsx`

1. Install the appropriate CodeMirror plugin for the new language.
1. Update the `languageExtensions` variable to include the new language CodeMirror plugin.

## Step 7: Add AST components
## Step 7: Wire the AST

In the `src/components/ast` directory, create two files:

1. `{new language}-ast.tsx`
1. `{new language}-ast-tree-item.tsx`

Replace `{new language}` with the name of the language. You can copy existing files for other languages to get started.

In `{new language}-ast-tree-item.tsx`, update the name of the options type and the exported component to match the new language.

Next, install the ESLint language plugin for the new language.

In `{new language}-ast.tsx`:

1. Update language references to point to the new language.
1. Import the ESLint language plugin to parse the code.
1. Set the `defaultValue` in the accordion to the name of the root node for the new language AST.

Last, update `src/components/index.tsx` to import `{new language}-ast.tsx` and update `Ast` to include the new language.
Add a parsing case in `src/hooks/use-ast.ts` for the new language that produces `{ ok: true, ast }`.
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@ import { TreeEntry } from "../tree-entry";
import type { FC } from "react";
import { mergeClassNames } from "@/lib/utils";

type ASTNode = {
export type ASTNode = {
readonly type: string;
readonly [key: string]: unknown;
};

export type CssAstTreeItemProperties = {
export type ASTTreeItemProperties = {
readonly index: number;
readonly data: ASTNode;
readonly esqueryMatchedNodes: ASTNode[];
};

export const CssAstTreeItem: FC<CssAstTreeItemProperties> = ({
export const ASTTreeItem: FC<ASTTreeItemProperties> = ({
data,
index,
esqueryMatchedNodes,
Expand Down
43 changes: 11 additions & 32 deletions src/components/ast/ast-view-mode.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,22 @@
import type { FC } from "react";
import { useExplorer } from "@/hooks/use-explorer";
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
import { astViewOptions } from "@/lib/const";
import { mergeClassNames } from "@/lib/utils";
import type { FC } from "react";
import { ViewModeToggle } from "@/components/view-mode-toggle";

export const AstViewMode: FC = () => {
const { viewModes, setViewModes } = useExplorer();
const { astView } = viewModes;

const handleValueChange = (value: string) => {
if (!value) {
return;
}

setViewModes({ ...viewModes, astView: value as "tree" | "json" });
};

return (
<ToggleGroup
type="single"
<ViewModeToggle
value={astView}
onValueChange={handleValueChange}
className="border rounded-md"
>
{astViewOptions.map(option => (
<ToggleGroupItem
key={option.value}
value={option.value}
className={mergeClassNames(
"border -m-px flex items-center gap-1.5",
option.value === astView
? "!bg-background"
: "border-transparent hover:bg-transparent text-muted-foreground",
)}
>
<option.icon size={16} />
{option.label}
</ToggleGroupItem>
))}
</ToggleGroup>
options={astViewOptions}
onValueChange={value =>
setViewModes({
...viewModes,
astView: value as "tree" | "json",
})
}
/>
);
};
44 changes: 0 additions & 44 deletions src/components/ast/css-ast.tsx

This file was deleted.

52 changes: 0 additions & 52 deletions src/components/ast/html-ast-tree-item.tsx

This file was deleted.

44 changes: 0 additions & 44 deletions src/components/ast/html-ast.tsx

This file was deleted.

61 changes: 42 additions & 19 deletions src/components/ast/index.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,47 @@
import { useExplorer } from "@/hooks/use-explorer";
import { JavascriptAst } from "./javascript-ast";
import { JsonAst } from "./json-ast";
import { CssAst } from "./css-ast";
import { MarkdownAst } from "./markdown-ast";
import { HtmlAst } from "./html-ast";
import type { FC } from "react";
import { useAST } from "@/hooks/use-ast";
import { useExplorer } from "@/hooks/use-explorer";
import { Accordion } from "@/components/ui/accordion";
import { Editor } from "@/components/editor";
import { parseError } from "@/lib/parse-error";
import { ErrorState } from "../error-boundary";
import { ASTTreeItem } from "./ast-tree-item";
import type { ASTNode } from "./ast-tree-item";

export const Ast: FC = () => {
const { language } = useExplorer();
export const AST: FC = () => {
const result = useAST();
const { viewModes, language } = useExplorer();
const { astView } = viewModes;

switch (language) {
case "markdown":
return <MarkdownAst />;
case "json":
return <JsonAst />;
case "css":
return <CssAst />;
case "html":
return <HtmlAst />;
default:
return <JavascriptAst />;
if (!result.ok) {
const message = parseError(result.errors[0]);
return <ErrorState message={message} />;
}

const ast = JSON.stringify(result.ast, null, 2);

if (astView === "tree") {
if (result.ast === null) {
return null;
}

return (
<Accordion
type="multiple"
className="px-8 pb-4 font-mono space-y-3 min-w-max"
key={`${language}`}
defaultValue={[`0-${(result.ast as ASTNode).type}`]}
>
<ASTTreeItem
data={result.ast as ASTNode}
index={0}
esqueryMatchedNodes={
result.esqueryMatchedNodes as ASTNode[]
}
/>
</Accordion>
);
}

return <Editor readOnly value={ast} />;
};
50 changes: 0 additions & 50 deletions src/components/ast/javascript-ast-tree-item.tsx

This file was deleted.

Loading