Revert "Upgrade linter and formatter to Ultracite" (#1226)

This commit is contained in:
josh 2025-09-21 12:03:29 +01:00 committed by GitHub
parent 0e320b391d
commit 1aff7d9868
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
177 changed files with 8334 additions and 6943 deletions

View file

@ -1,15 +1,15 @@
import { textblockTypeInputRule } from "prosemirror-inputrules";
import { Schema } from "prosemirror-model";
import { schema } from "prosemirror-schema-basic";
import { addListNodes } from "prosemirror-schema-list";
import type { Transaction } from "prosemirror-state";
import type { EditorView } from "prosemirror-view";
import type { MutableRefObject } from "react";
import { textblockTypeInputRule } from 'prosemirror-inputrules';
import { Schema } from 'prosemirror-model';
import { schema } from 'prosemirror-schema-basic';
import { addListNodes } from 'prosemirror-schema-list';
import type { Transaction } from 'prosemirror-state';
import type { EditorView } from 'prosemirror-view';
import type { MutableRefObject } from 'react';
import { buildContentFromDocument } from "./functions";
import { buildContentFromDocument } from './functions';
export const documentSchema = new Schema({
nodes: addListNodes(schema.spec.nodes, "paragraph block*", "block"),
nodes: addListNodes(schema.spec.nodes, 'paragraph block*', 'block'),
marks: schema.spec.marks,
});
@ -17,7 +17,7 @@ export function headingRule(level: number) {
return textblockTypeInputRule(
new RegExp(`^(#{1,${level}})\\s$`),
documentSchema.nodes.heading,
() => ({ level })
() => ({ level }),
);
}
@ -30,17 +30,15 @@ export const handleTransaction = ({
editorRef: MutableRefObject<EditorView | null>;
onSaveContent: (updatedContent: string, debounce: boolean) => void;
}) => {
if (!editorRef || !editorRef.current) {
return;
}
if (!editorRef || !editorRef.current) return;
const newState = editorRef.current.state.apply(transaction);
editorRef.current.updateState(newState);
if (transaction.docChanged && !transaction.getMeta("no-save")) {
if (transaction.docChanged && !transaction.getMeta('no-save')) {
const updatedContent = buildContentFromDocument(newState.doc);
if (transaction.getMeta("no-debounce")) {
if (transaction.getMeta('no-debounce')) {
onSaveContent(updatedContent, false);
} else {
onSaveContent(updatedContent, true);

View file

@ -1,7 +1,7 @@
// Modified from https://github.com/hamflx/prosemirror-diff/blob/master/src/diff.js
import { diff_match_patch } from "diff-match-patch";
import { Fragment, Node } from "prosemirror-model";
import { diff_match_patch } from 'diff-match-patch';
import { Fragment, Node } from 'prosemirror-model';
export const DiffType = {
Unchanged: 0,
@ -49,7 +49,7 @@ export const patchDocumentNode = (schema, oldNode, newNode) => {
const matchedNodes = matchNodes(
schema,
diffOldChildren,
diffNewChildren
diffNewChildren,
).sort((a, b) => b.count - a.count);
const bestMatch = matchedNodes[0];
if (bestMatch) {
@ -62,11 +62,11 @@ export const patchDocumentNode = (schema, oldNode, newNode) => {
...patchRemainNodes(
schema,
oldBeforeMatchChildren,
newBeforeMatchChildren
)
newBeforeMatchChildren,
),
);
finalLeftChildren.push(
...diffOldChildren.slice(oldStartIndex, oldEndIndex)
...diffOldChildren.slice(oldStartIndex, oldEndIndex),
);
const oldAfterMatchChildren = diffOldChildren.slice(oldEndIndex);
@ -76,24 +76,24 @@ export const patchDocumentNode = (schema, oldNode, newNode) => {
...patchRemainNodes(
schema,
oldAfterMatchChildren,
newAfterMatchChildren
)
newAfterMatchChildren,
),
);
} else {
finalLeftChildren.push(
...patchRemainNodes(schema, diffOldChildren, diffNewChildren)
...patchRemainNodes(schema, diffOldChildren, diffNewChildren),
);
}
} else {
finalLeftChildren.push(
...patchRemainNodes(schema, diffOldChildren, diffNewChildren)
...patchRemainNodes(schema, diffOldChildren, diffNewChildren),
);
}
return createNewNode(oldNode, [...finalLeftChildren, ...finalRightChildren]);
};
const matchNodes = (_schema, oldChildren, newChildren) => {
const matchNodes = (schema, oldChildren, newChildren) => {
const matches = [];
for (
let oldStartIndex = 0;
@ -155,7 +155,7 @@ const patchRemainNodes = (schema, oldChildren, newChildren) => {
!isTextNode(rightOldNode) && matchNodeType(rightOldNode, rightNewNode);
if (Array.isArray(leftOldNode) && Array.isArray(leftNewNode)) {
finalLeftChildren.push(
...patchTextNodes(schema, leftOldNode, leftNewNode)
...patchTextNodes(schema, leftOldNode, leftNewNode),
);
left += 1;
continue;
@ -165,7 +165,7 @@ const patchRemainNodes = (schema, oldChildren, newChildren) => {
const equalityLeft = computeChildEqualityFactor(leftOldNode, leftNewNode);
const equalityRight = computeChildEqualityFactor(
rightOldNode,
rightNewNode
rightNewNode,
);
if (equalityLeft < equalityRight) {
updateLeft = false;
@ -175,21 +175,21 @@ const patchRemainNodes = (schema, oldChildren, newChildren) => {
}
if (updateLeft) {
finalLeftChildren.push(
patchDocumentNode(schema, leftOldNode, leftNewNode)
patchDocumentNode(schema, leftOldNode, leftNewNode),
);
left += 1;
} else if (updateRight) {
finalRightChildren.unshift(
patchDocumentNode(schema, rightOldNode, rightNewNode)
patchDocumentNode(schema, rightOldNode, rightNewNode),
);
right += 1;
} else {
// Delete and insert
finalLeftChildren.push(
createDiffNode(schema, leftOldNode, DiffType.Deleted)
createDiffNode(schema, leftOldNode, DiffType.Deleted),
);
finalLeftChildren.push(
createDiffNode(schema, leftNewNode, DiffType.Inserted)
createDiffNode(schema, leftNewNode, DiffType.Inserted),
);
left += 1;
}
@ -202,7 +202,7 @@ const patchRemainNodes = (schema, oldChildren, newChildren) => {
...oldChildren
.slice(left, left + deleteNodeLen)
.flat()
.map((node) => createDiffNode(schema, node, DiffType.Deleted))
.map((node) => createDiffNode(schema, node, DiffType.Deleted)),
);
}
@ -211,7 +211,7 @@ const patchRemainNodes = (schema, oldChildren, newChildren) => {
...newChildren
.slice(left, left + insertNodeLen)
.flat()
.map((node) => createDiffNode(schema, node, DiffType.Inserted))
.map((node) => createDiffNode(schema, node, DiffType.Inserted)),
);
}
@ -223,8 +223,8 @@ export const patchTextNodes = (schema, oldNode, newNode) => {
const dmp = new diff_match_patch();
// Concatenate the text from the text nodes
const oldText = oldNode.map((n) => getNodeText(n)).join("");
const newText = newNode.map((n) => getNodeText(n)).join("");
const oldText = oldNode.map((n) => getNodeText(n)).join('');
const newText = newNode.map((n) => getNodeText(n)).join('');
// Tokenize the text into sentences
const oldSentences = tokenizeSentences(oldText);
@ -233,7 +233,7 @@ export const patchTextNodes = (schema, oldNode, newNode) => {
// Map sentences to unique characters
const { chars1, chars2, lineArray } = sentencesToChars(
oldSentences,
newSentences
newSentences,
);
// Perform the diff
@ -242,7 +242,7 @@ export const patchTextNodes = (schema, oldNode, newNode) => {
// Convert back to sentences
diffs = diffs.map(([type, text]) => {
const sentences = text
.split("")
.split('')
.map((char) => lineArray[char.charCodeAt(0)]);
return [type, sentences];
});
@ -253,7 +253,7 @@ export const patchTextNodes = (schema, oldNode, newNode) => {
const node = createTextNode(
schema,
sentence,
type !== DiffType.Unchanged ? [createDiffMark(schema, type)] : []
type !== DiffType.Unchanged ? [createDiffMark(schema, type)] : [],
);
return node;
});
@ -284,7 +284,7 @@ const sentencesToChars = (oldSentences, newSentences) => {
lineStart++;
return String.fromCharCode(lineHash[line]);
})
.join("");
.join('');
const chars2 = newSentences
.map((sentence) => {
@ -297,17 +297,17 @@ const sentencesToChars = (oldSentences, newSentences) => {
lineStart++;
return String.fromCharCode(lineHash[line]);
})
.join("");
.join('');
return { chars1, chars2, lineArray };
};
export const computeChildEqualityFactor = (_node1, _node2) => {
export const computeChildEqualityFactor = (node1, node2) => {
return 0;
};
export const assertNodeTypeEqual = (node1, node2) => {
if (getNodeProperty(node1, "type") !== getNodeProperty(node2, "type")) {
if (getNodeProperty(node1, 'type') !== getNodeProperty(node2, 'type')) {
throw new Error(`node type not equal: ${node1.type} !== ${node2.type}`);
}
};
@ -329,14 +329,14 @@ export const isNodeEqual = (node1, node2) => {
);
}
const type1 = getNodeProperty(node1, "type");
const type2 = getNodeProperty(node2, "type");
const type1 = getNodeProperty(node1, 'type');
const type2 = getNodeProperty(node2, 'type');
if (type1 !== type2) {
return false;
}
if (isTextNode(node1)) {
const text1 = getNodeProperty(node1, "text");
const text2 = getNodeProperty(node2, "text");
const text1 = getNodeProperty(node1, 'text');
const text2 = getNodeProperty(node2, 'text');
if (text1 !== text2) {
return false;
}
@ -396,7 +396,7 @@ export const normalizeNodeContent = (node) => {
};
export const getNodeProperty = (node, property) => {
if (property === "type") {
if (property === 'type') {
return node.type?.name;
}
return node[property];
@ -413,7 +413,7 @@ export const getNodeChildren = (node) => node.content?.content ?? [];
export const getNodeText = (node) => node.text;
export const isTextNode = (node) => node.type?.name === "text";
export const isTextNode = (node) => node.type?.name === 'text';
export const matchNodeType = (node1, node2) =>
node1.type?.name === node2.type?.name ||
@ -421,25 +421,25 @@ export const matchNodeType = (node1, node2) =>
export const createNewNode = (oldNode, children) => {
if (!oldNode.type) {
throw new Error("oldNode.type is undefined");
throw new Error('oldNode.type is undefined');
}
return new Node(
oldNode.type,
oldNode.attrs,
Fragment.fromArray(children),
oldNode.marks
oldNode.marks,
);
};
export const createDiffNode = (schema, node, type) => {
return mapDocumentNode(node, (currentNode) => {
if (isTextNode(currentNode)) {
return createTextNode(schema, getNodeText(currentNode), [
...(currentNode.marks || []),
return mapDocumentNode(node, (node) => {
if (isTextNode(node)) {
return createTextNode(schema, getNodeText(node), [
...(node.marks || []),
createDiffMark(schema, type),
]);
}
return currentNode;
return node;
});
};
@ -447,21 +447,21 @@ function mapDocumentNode(node, mapper) {
const copy = node.copy(
Fragment.from(
node.content.content
.map((currentNode) => mapDocumentNode(currentNode, mapper))
.filter((n) => n)
)
.map((node) => mapDocumentNode(node, mapper))
.filter((n) => n),
),
);
return mapper(copy) || copy;
}
export const createDiffMark = (schema, type) => {
if (type === DiffType.Inserted) {
return schema.mark("diffMark", { type });
return schema.mark('diffMark', { type });
}
if (type === DiffType.Deleted) {
return schema.mark("diffMark", { type });
return schema.mark('diffMark', { type });
}
throw new Error("type is not valid");
throw new Error('type is not valid');
};
export const createTextNode = (schema, content, marks = []) => {

View file

@ -1,19 +1,19 @@
"use client";
'use client';
import { defaultMarkdownSerializer } from "prosemirror-markdown";
import { DOMParser, type Node } from "prosemirror-model";
import { Decoration, DecorationSet, type EditorView } from "prosemirror-view";
import { renderToString } from "react-dom/server";
import { defaultMarkdownSerializer } from 'prosemirror-markdown';
import { DOMParser, type Node } from 'prosemirror-model';
import { Decoration, DecorationSet, type EditorView } from 'prosemirror-view';
import { renderToString } from 'react-dom/server';
import { Response } from "@/components/elements/response";
import { Response } from '@/components/elements/response';
import { documentSchema } from "./config";
import { createSuggestionWidget, type UISuggestion } from "./suggestions";
import { documentSchema } from './config';
import { createSuggestionWidget, type UISuggestion } from './suggestions';
export const buildDocumentFromContent = (content: string) => {
const parser = DOMParser.fromSchema(documentSchema);
const stringFromMarkdown = renderToString(<Response>{content}</Response>);
const tempContainer = document.createElement("div");
const tempContainer = document.createElement('div');
tempContainer.innerHTML = stringFromMarkdown;
return parser.parse(tempContainer);
};
@ -23,10 +23,10 @@ export const buildContentFromDocument = (document: Node) => {
};
export const createDecorations = (
suggestions: UISuggestion[],
view: EditorView
suggestions: Array<UISuggestion>,
view: EditorView,
) => {
const decorations: Decoration[] = [];
const decorations: Array<Decoration> = [];
for (const suggestion of suggestions) {
decorations.push(
@ -34,27 +34,27 @@ export const createDecorations = (
suggestion.selectionStart,
suggestion.selectionEnd,
{
class: "suggestion-highlight",
class: 'suggestion-highlight',
},
{
suggestionId: suggestion.id,
type: "highlight",
}
)
type: 'highlight',
},
),
);
decorations.push(
Decoration.widget(
suggestion.selectionStart,
(currentView) => {
const { dom } = createSuggestionWidget(suggestion, currentView);
(view) => {
const { dom } = createSuggestionWidget(suggestion, view);
return dom;
},
{
suggestionId: suggestion.id,
type: "widget",
}
)
type: 'widget',
},
),
);
}

View file

@ -1,6 +1,5 @@
import { createRoot } from "react-dom/client";
import { createRoot } from 'react-dom/client';
// biome-ignore lint/complexity/noStaticOnlyClass: "Needs to be static"
export class ReactRenderer {
static render(component: React.ReactElement, dom: HTMLElement) {
const root = createRoot(dom);

View file

@ -1,24 +1,25 @@
import type { Node } from "prosemirror-model";
import { Plugin, PluginKey } from "prosemirror-state";
import type { Node } from 'prosemirror-model';
import { Plugin, PluginKey } from 'prosemirror-state';
import {
type Decoration,
DecorationSet,
type EditorView,
} from "prosemirror-view";
import { createRoot } from "react-dom/client";
import type { ArtifactKind } from "@/components/artifact";
import { Suggestion as PreviewSuggestion } from "@/components/suggestion";
import type { Suggestion } from "@/lib/db/schema";
} from 'prosemirror-view';
import { createRoot } from 'react-dom/client';
import { Suggestion as PreviewSuggestion } from '@/components/suggestion';
import type { Suggestion } from '@/lib/db/schema';
import type { ArtifactKind } from '@/components/artifact';
export interface UISuggestion extends Suggestion {
selectionStart: number;
selectionEnd: number;
}
type Position = {
interface Position {
start: number;
end: number;
};
}
function findPositionsInDoc(doc: Node, searchText: string): Position | null {
let positions: { start: number; end: number } | null = null;
@ -45,8 +46,8 @@ function findPositionsInDoc(doc: Node, searchText: string): Position | null {
export function projectWithPositions(
doc: Node,
suggestions: Suggestion[]
): UISuggestion[] {
suggestions: Array<Suggestion>,
): Array<UISuggestion> {
return suggestions.map((suggestion) => {
const positions = findPositionsInDoc(doc, suggestion.originalText);
@ -69,12 +70,12 @@ export function projectWithPositions(
export function createSuggestionWidget(
suggestion: UISuggestion,
view: EditorView,
artifactKind: ArtifactKind = "text"
artifactKind: ArtifactKind = 'text',
): { dom: HTMLElement; destroy: () => void } {
const dom = document.createElement("span");
const dom = document.createElement('span');
const root = createRoot(dom);
dom.addEventListener("mousedown", (event) => {
dom.addEventListener('mousedown', (event) => {
event.preventDefault();
view.dom.blur();
});
@ -91,7 +92,7 @@ export function createSuggestionWidget(
state.doc,
currentDecorations.find().filter((decoration: Decoration) => {
return decoration.spec.suggestionId !== suggestion.id;
})
}),
);
decorationTransaction.setMeta(suggestionsPluginKey, {
@ -104,20 +105,20 @@ export function createSuggestionWidget(
const textTransaction = view.state.tr.replaceWith(
suggestion.selectionStart,
suggestion.selectionEnd,
state.schema.text(suggestion.suggestedText)
state.schema.text(suggestion.suggestedText),
);
textTransaction.setMeta("no-debounce", true);
textTransaction.setMeta('no-debounce', true);
dispatch(textTransaction);
};
root.render(
<PreviewSuggestion
artifactKind={artifactKind}
onApply={onApply}
suggestion={suggestion}
/>
onApply={onApply}
artifactKind={artifactKind}
/>,
);
return {
@ -131,7 +132,7 @@ export function createSuggestionWidget(
};
}
export const suggestionsPluginKey = new PluginKey("suggestions");
export const suggestionsPluginKey = new PluginKey('suggestions');
export const suggestionsPlugin = new Plugin({
key: suggestionsPluginKey,
state: {
@ -140,9 +141,7 @@ export const suggestionsPlugin = new Plugin({
},
apply(tr, state) {
const newDecorations = tr.getMeta(suggestionsPluginKey);
if (newDecorations) {
return newDecorations;
}
if (newDecorations) return newDecorations;
return {
decorations: state.decorations.map(tr.mapping, tr.doc),