Skip to content

Commit

Permalink
WIP. editor. syntaxParsingCache code review
Browse files Browse the repository at this point in the history
  • Loading branch information
maxzz committed Jan 7, 2024
1 parent f1cd6a6 commit 4133e03
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 61 deletions.
18 changes: 3 additions & 15 deletions src/components/ui/editor/Code.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,7 @@ type CodeProps = {

export function Code({ className = "", code, language = "jsx", showLineNumbers = false, }: CodeProps) {
return (
<Suspense
fallback={
<Fallback
className={className}
code={code}
showLineNumbers={showLineNumbers}
/>
}
>
<Suspense fallback={<Fallback className={className} code={code} showLineNumbers={showLineNumbers} />} >
<Parser
className={className}
code={code}
Expand All @@ -52,7 +44,7 @@ function Fallback({ className, code, showLineNumbers, }: { className: string; co

return escaped;
});
}, [showLineNumbers, code]);
}, [code, showLineNumbers]);

const maxLineNumberLength = `${htmlLines.length + 1}`.length;

Expand All @@ -68,11 +60,7 @@ function Fallback({ className, code, showLineNumbers, }: { className: string; co
function Parser({ className, code, language, showLineNumbers, }: { className: string; code: string; language: Language; showLineNumbers: boolean; }) {
const tokens = syntaxParsingCache.read(code, language);
return (
<TokenRenderer
className={className}
tokens={tokens}
showLineNumbers={showLineNumbers}
/>
<TokenRenderer className={className} tokens={tokens} showLineNumbers={showLineNumbers} />
);
}

Expand Down
File renamed without changes.
File renamed without changes.
4 changes: 2 additions & 2 deletions src/components/ui/editor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
// https://github.com/bvaughn/react-resizable-panels/blob/main/packages/react-resizable-panels-website/src/routes/examples/ImperativePanelApi.tsx#L57
// https://github.com/bvaughn/react-resizable-panels/blob/main/packages/react-resizable-panels-website/src/routes/examples/Example.tsx#L9

import "./root.css";
import "./code-mirror.css";
import "./codemirror-root.css";
import "./codemirror.css";

export * from "./suspense/syntax-parsing-cache";
export * from "./code";
80 changes: 36 additions & 44 deletions src/components/ui/editor/suspense/syntax-parsing-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,21 @@ export type ParserData = {
rawTextPercentage: number;
};

type CurrentLineState = {
parsedTokens: ParsedTokens;
rawString: string;
};

export const DEFAULT_MAX_CHARACTERS = 500_000;
export const DEFAULT_MAX_TIME = 5_000;

export const syntaxParsingCache = createCache<[code: string, language: Language], ParsedTokens[]>({
config: { immutable: true },
debugLabel: "syntaxParsingCache",
getKey: ([code, language]) => `${code}-${language}`,

load: async ([code, language]) => {
const languageExtension = await getLanguageExtension(language);
const parsedTokens: ParsedTokens[] = [];

const currentLineState = {
parsedTokens: [] as ParsedTokens,
rawString: "",
};

// The logic below to trim code sections only works with "\n"
code = code.replace(/\r\n?|\n|\u2028|\u2029/g, "\n");
Expand All @@ -60,31 +60,31 @@ export const syntaxParsingCache = createCache<[code: string, language: Language]
code = code.slice(0, index + 1);
}

const state = EditorState.create({
doc: code,
extensions: [languageExtension],
});
const state = EditorState.create({ doc: code, extensions: [languageExtension], });

const tree = ensureSyntaxTree(state!, DEFAULT_MAX_CHARACTERS, DEFAULT_MAX_TIME);
if (tree === null) {
if (!tree) {
return [];
}

const rv: ParsedTokens[] = [];
const currentLineState: CurrentLineState = {
parsedTokens: [],
rawString: "",
};

let characterIndex = 0;
let parsedCharacterIndex = 0;

highlightTree(
tree,
classHighlighter,
(from: number, to: number, className: string) => {
highlightTree(tree, classHighlighter,
(from: number, to: number, tokenClassName: string) => {
if (from > characterIndex) {
// No style applied to the token between position and from.
// This typically indicates white space or newline characters.
processSection(currentLineState, parsedTokens, code.slice(characterIndex, from), "");
// This typically indicates whitespace or newline characters.
const whitespace = code.slice(characterIndex, from);
processSection(currentLineState, rv, whitespace, "");
}

processSection(currentLineState, parsedTokens, code.slice(from, to), className);

const token = code.slice(from, to);
processSection(currentLineState, rv, token, tokenClassName);
characterIndex = to;
}
);
Expand All @@ -93,13 +93,14 @@ export const syntaxParsingCache = createCache<[code: string, language: Language]
if (characterIndex < maxPosition) {
// No style applied on the trailing text.
// This typically indicates white space or newline characters.
processSection(currentLineState, parsedTokens, code.slice(characterIndex, maxPosition), "");
processSection(currentLineState, rv, code.slice(characterIndex, maxPosition), "");
}

if (currentLineState.parsedTokens.length) {
parsedTokens.push(currentLineState.parsedTokens);
rv.push(currentLineState.parsedTokens);
}

let parsedCharacterIndex = 0;
parsedCharacterIndex += characterIndex + 1;

// Anything that's left should de-opt to plain text.
Expand All @@ -109,10 +110,9 @@ export const syntaxParsingCache = createCache<[code: string, language: Language]
let parsedLineTokens: ParsedToken[] = [];

while (true) {
const line =
nextIndex >= 0
? code.substring(parsedCharacterIndex, nextIndex)
: code.substring(parsedCharacterIndex);
const line = nextIndex >= 0
? code.substring(parsedCharacterIndex, nextIndex)
: code.substring(parsedCharacterIndex);

parsedLineTokens.push({
columnIndex: 0,
Expand All @@ -121,10 +121,11 @@ export const syntaxParsingCache = createCache<[code: string, language: Language]
});

if (nextIndex >= 0) {
parsedTokens.push(parsedLineTokens);
rv.push(parsedLineTokens);

parsedLineTokens = [];
} else if (nextIndex === -1) {
}
else if (nextIndex === -1) {
break;
}

Expand All @@ -133,33 +134,24 @@ export const syntaxParsingCache = createCache<[code: string, language: Language]
}

if (parsedLineTokens.length) {
parsedTokens.push(parsedLineTokens);
rv.push(parsedLineTokens);
}
}

return parsedTokens;
return rv;
},
});

function processSection(
currentLineState: {
parsedTokens: ParsedTokens;
rawString: string;
},
parsedTokens: ParsedTokens[],
section: string,
className: string
) {
function processSection(currentLineState: CurrentLineState, parsedTokens: ParsedTokens[], section: string, className: string) {
const tokenType = className?.substring(4) ?? null; // Remove "tok-" prefix;

let index = 0;
let nextIndex = section.indexOf("\n");

while (true) {
const substring =
nextIndex >= 0
? section.substring(index, nextIndex)
: section.substring(index);
const substring = nextIndex >= 0
? section.substring(index, nextIndex)
: section.substring(index);

const token: ParsedToken = {
columnIndex: currentLineState.rawString.length,
Expand Down
3 changes: 3 additions & 0 deletions vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ function manualChunks(id: string) { //https://rollupjs.org/configuration-options
if (id.includes("recharts")) {
return "recharts";
}
if (id.includes("@codemirror")) {
return "codemirror";
}
// if (id.includes("node_modules")) {
// return "vendor";
// }
Expand Down

0 comments on commit 4133e03

Please sign in to comment.