Format files with prettier

This commit is contained in:
Andras Schmelczer 2025-07-06 22:21:17 +01:00
parent a2df120e66
commit 1ce0f9c059
No known key found for this signature in database
GPG key ID: FC8F2C3D3D1A718C
9 changed files with 5988 additions and 5997 deletions

View file

@ -3,8 +3,5 @@
"printWidth": 90, "printWidth": 90,
"tabWidth": 2, "tabWidth": 2,
"singleQuote": true, "singleQuote": true,
"endOfLine": "lf", "endOfLine": "lf"
"importOrder": ["^[./]", ".*", ".scss$"], }
"importOrderSeparation": true,
"importOrderSortSpecifiers": true
}

View file

@ -1,38 +1,32 @@
{ {
"name": "portfolio", "name": "reconcile-example-website",
"description": "An easily configurable timeline of projects.", "description": "",
"private": true, "private": true,
"scripts": { "scripts": {
"start": "webpack serve --open --mode development", "start": "webpack serve --open --mode development",
"format": "prettier --write \"src/**/*.(ts|scss|json|html)\"", "format": "prettier --write \"./**/*.(ts|scss|json|html)\"",
"build": "webpack --mode production" "build": "webpack --mode production"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/schmelczer/schmelczer.github.io.git" "url": "git+https://github.com/schmelczer/reconcile.git"
}, },
"keywords": [ "keywords": [],
"CV",
"curriculum",
"vitae",
"portfolio",
"resumé"
],
"author": "Andras Schmelczer", "author": "Andras Schmelczer",
"license": "GPL-3.0-or-later", "license": "GPL-3.0-or-later",
"bugs": { "bugs": {
"url": "https://github.com/schmelczer/schmelczer.github.io/issues" "url": "https://github.com/schmelczer/reconcile/issues"
}, },
"browserslist": [ "browserslist": [
"defaults" "defaults"
], ],
"homepage": "https://github.com/schmelczer/schmelczer.github.io#readme", "homepage": "https://github.com/schmelczer/reconcile#readme",
"devDependencies": { "devDependencies": {
"reconcile": "file:../../reconcile-js", "reconcile": "file:../../reconcile-js",
"css-loader": "^7.1.2", "css-loader": "^7.1.2",
"html-webpack-plugin": "^5.6.3", "html-webpack-plugin": "^5.6.3",
"inline-source-webpack-plugin": "^3.0.1",
"mini-css-extract-plugin": "^2.9.2", "mini-css-extract-plugin": "^2.9.2",
"inline-source-webpack-plugin": "^3.0.1",
"prettier": "^3.6.2", "prettier": "^3.6.2",
"resolve-url-loader": "^5.0.0", "resolve-url-loader": "^5.0.0",
"sass": "^1.89.2", "sass": "^1.89.2",

View file

@ -1,19 +1,17 @@
{ {
"compilerOptions": { "compilerOptions": {
"module": "ESNext", "module": "ESNext",
"target": "ESNext", "target": "ESNext",
"strict": true, "strict": true,
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"esModuleInterop": true, "esModuleInterop": true,
"moduleResolution": "bundler", "moduleResolution": "bundler",
"declaration": true, "declaration": true,
"declarationDir": "./dist/types", "declarationDir": "./dist/types",
"outDir": "./dist", "outDir": "./dist",
"rootDir": ".", "rootDir": ".",
"skipLibCheck": true, "skipLibCheck": true,
"inlineSourceMap": true "inlineSourceMap": true
}, },
"exclude": [ "exclude": ["./dist"]
"./dist" }
]
}

File diff suppressed because it is too large Load diff

View file

@ -1,24 +1,26 @@
{ {
"name": "reconcile", "name": "reconcile",
"version": "0.4.0", "version": "0.4.0",
"main": "dist/index.js", "main": "dist/index.js",
"types": "dist/types/index.d.ts", "types": "dist/types/index.d.ts",
"files": [ "files": [
"dist/*" "dist/*"
], ],
"scripts": { "scripts": {
"build": "webpack --mode production", "build": "webpack --mode production",
"test": "NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" jest" "format": "prettier --write \"./**/*.(ts|scss|json|html)\"",
}, "test": "NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" jest"
"devDependencies": { },
"@types/jest": "^30.0.0", "devDependencies": {
"jest": "^30.0.4", "@types/jest": "^30.0.0",
"reconcile": "file:../pkg", "jest": "^30.0.4",
"ts-jest": "^29.4.0", "reconcile": "file:../pkg",
"ts-loader": "^9.5.2", "ts-jest": "^29.4.0",
"tslib": "2.8.1", "ts-loader": "^9.5.2",
"typescript": "5.8.3", "tslib": "2.8.1",
"webpack": "^5.99.9", "typescript": "5.8.3",
"webpack-cli": "^6.0.1" "webpack": "^5.99.9",
} "webpack-cli": "^6.0.1",
} "prettier": "^3.6.2"
}
}

View file

@ -1,70 +1,66 @@
import { init, reconcile, reconcileWithHistory } from "./index"; import { init, reconcile, reconcileWithHistory } from './index';
import * as fs from "fs"; import * as fs from 'fs';
describe("reconcile", () => { describe('reconcile', () => {
it("tries calling functions without init", () => { it('tries calling functions without init', () => {
expect(() => reconcile("Hello", "Hello world", "Hi world")).toThrow( expect(() => reconcile('Hello', 'Hello world', 'Hi world')).toThrow(/call init()/);
/call init()/
);
expect(() => expect(() => reconcileWithHistory('Hello', 'Hello world', 'Hi world')).toThrow(
reconcileWithHistory("Hello", "Hello world", "Hi world") /call init()/
).toThrow(/call init()/); );
}); });
it("call reconcile without cursors", async () => { it('call reconcile without cursors', async () => {
await initWasm(); await initWasm();
expect(reconcile("Hello", "Hello world", "Hi world").text).toEqual( expect(reconcile('Hello', 'Hello world', 'Hi world').text).toEqual('Hi world');
"Hi world" });
);
});
it("call reconcile with cursors", async () => { it('call reconcile with cursors', async () => {
await initWasm(); await initWasm();
const result = reconcile( const result = reconcile(
"Hello", 'Hello',
{ {
text: "Hello world", text: 'Hello world',
cursors: [ cursors: [
{ {
id: 3, id: 3,
position: 2, position: 2,
}, },
], ],
}, },
{ {
text: "Hi world", text: 'Hi world',
cursors: [ cursors: [
{ {
id: 4, id: 4,
position: 0, position: 0,
}, },
{ id: 5, position: 3 }, { id: 5, position: 3 },
], ],
} }
); );
expect(result.text).toEqual("Hi world"); expect(result.text).toEqual('Hi world');
expect(result.cursors).toEqual([ expect(result.cursors).toEqual([
{ id: 3, position: 0 }, { id: 3, position: 0 },
{ id: 4, position: 0 }, { id: 4, position: 0 },
{ id: 5, position: 3 }, { id: 5, position: 3 },
]); ]);
}); });
it("call reconcileWithHistory", async () => { it('call reconcileWithHistory', async () => {
await initWasm(); await initWasm();
const result = reconcileWithHistory("Hello", "Hello world", "Hi world"); const result = reconcileWithHistory('Hello', 'Hello world', 'Hi world');
expect(result.text).toEqual("Hi world"); expect(result.text).toEqual('Hi world');
expect(result.history.length).toBeGreaterThan(0); expect(result.history.length).toBeGreaterThan(0);
}); });
}); });
async function initWasm() { async function initWasm() {
const wasmBin = fs.readFileSync("../pkg/reconcile_bg.wasm"); const wasmBin = fs.readFileSync('../pkg/reconcile_bg.wasm');
await init({ module_or_path: wasmBin }); await init({ module_or_path: wasmBin });
} }

View file

@ -1,54 +1,54 @@
import wasmInit, { import wasmInit, {
CursorPosition as wasmCursorPosition, CursorPosition as wasmCursorPosition,
reconcile as wasmReconcile, reconcile as wasmReconcile,
TextWithCursors as wasmTextWithCursors, TextWithCursors as wasmTextWithCursors,
SpanWithHistory as wasmSpanWithHistory, SpanWithHistory as wasmSpanWithHistory,
BuiltinTokenizer, BuiltinTokenizer,
reconcileWithHistory as wasmReconcileWithHistory, reconcileWithHistory as wasmReconcileWithHistory,
History, History,
InitInput, InitInput,
} from "reconcile"; } from 'reconcile';
export interface TextWithCursors { export interface TextWithCursors {
/** The document's entire content */ /** The document's entire content */
text: string; text: string;
/** List of cursor positions, can be null or undefined if there are no cursors */ /** List of cursor positions, can be null or undefined if there are no cursors */
cursors: null | undefined | CursorPosition[]; cursors: null | undefined | CursorPosition[];
} }
export interface CursorPosition { export interface CursorPosition {
/** Unique identifier for the cursor */ /** Unique identifier for the cursor */
id: number; id: number;
/** Character position in the text, 0-based */ /** Character position in the text, 0-based */
position: number; position: number;
} }
export interface TextWithCursorsAndHistory { export interface TextWithCursorsAndHistory {
/** The document's entire content */ /** The document's entire content */
text: string; text: string;
/** List of cursor positions, can be null or undefined if there are no cursors */ /** List of cursor positions, can be null or undefined if there are no cursors */
cursors: null | undefined | CursorPosition[]; cursors: null | undefined | CursorPosition[];
/** List of operations leading to `text` from the 3 ancestors */ /** List of operations leading to `text` from the 3 ancestors */
history: SpanWithHistory[]; history: SpanWithHistory[];
} }
export interface SpanWithHistory { export interface SpanWithHistory {
/** Span of text associated with the historical opearion */ /** Span of text associated with the historical opearion */
text: string; text: string;
/** Origin of the `text` span */ /** Origin of the `text` span */
history: History; history: History;
} }
export type Tokenizer = "Line" | "Word" | "Character"; export type Tokenizer = 'Line' | 'Word' | 'Character';
const TOKENIZERS = ["Line", "Word", "Character"]; const TOKENIZERS = ['Line', 'Word', 'Character'];
let isInitialised = false; let isInitialised = false;
const UNINITIALISED_MODULE_ERROR = const UNINITIALISED_MODULE_ERROR =
"Reconcile module has not been initialized. Please call init() before using any other functions."; 'Reconcile module has not been initialized. Please call init() before using any other functions.';
const UNSUPPORTED_TOKENIZER_ERROR = `Unsupported tokenizer. Only ${TOKENIZERS.join( const UNSUPPORTED_TOKENIZER_ERROR = `Unsupported tokenizer. Only ${TOKENIZERS.join(
", " ', '
)} are supported.`; )} are supported.`;
/** /**
@ -61,13 +61,13 @@ const UNSUPPORTED_TOKENIZER_ERROR = `Unsupported tokenizer. Only ${TOKENIZERS.jo
* @returns Promise that resolves when initialization is complete * @returns Promise that resolves when initialization is complete
*/ */
export async function init(content?: InitInput) { export async function init(content?: InitInput) {
if (isInitialised) { if (isInitialised) {
return; return;
} }
await wasmInit(content); await wasmInit(content);
isInitialised = true; isInitialised = true;
} }
/** /**
@ -80,31 +80,31 @@ export async function init(content?: InitInput) {
* @returns The reconciled text with merged cursor positions * @returns The reconciled text with merged cursor positions
*/ */
export function reconcile( export function reconcile(
original: string, original: string,
left: string | TextWithCursors, left: string | TextWithCursors,
right: string | TextWithCursors, right: string | TextWithCursors,
tokenizer: BuiltinTokenizer = "Word" tokenizer: BuiltinTokenizer = 'Word'
): TextWithCursors { ): TextWithCursors {
if (!isInitialised) { if (!isInitialised) {
throw new Error(UNINITIALISED_MODULE_ERROR); throw new Error(UNINITIALISED_MODULE_ERROR);
} }
if (!TOKENIZERS.includes(tokenizer)) { if (!TOKENIZERS.includes(tokenizer)) {
throw new Error(UNSUPPORTED_TOKENIZER_ERROR); throw new Error(UNSUPPORTED_TOKENIZER_ERROR);
} }
const leftCursor = toWasmTextWithCursors(left); const leftCursor = toWasmTextWithCursors(left);
const rightCursor = toWasmTextWithCursors(right); const rightCursor = toWasmTextWithCursors(right);
const result = wasmReconcile(original, leftCursor, rightCursor, tokenizer); const result = wasmReconcile(original, leftCursor, rightCursor, tokenizer);
leftCursor.free(); leftCursor.free();
rightCursor.free(); rightCursor.free();
const jsResult = toTextWithCursors(result); const jsResult = toTextWithCursors(result);
result.free(); result.free();
return jsResult; return jsResult;
} }
/** /**
@ -119,83 +119,66 @@ export function reconcile(
* @returns The reconciled text with cursor positions and history of changes * @returns The reconciled text with cursor positions and history of changes
*/ */
export function reconcileWithHistory( export function reconcileWithHistory(
original: string, original: string,
left: string | TextWithCursors, left: string | TextWithCursors,
right: string | TextWithCursors, right: string | TextWithCursors,
tokenizer: BuiltinTokenizer = "Word" tokenizer: BuiltinTokenizer = 'Word'
): TextWithCursorsAndHistory { ): TextWithCursorsAndHistory {
if (!isInitialised) { if (!isInitialised) {
throw new Error(UNINITIALISED_MODULE_ERROR); throw new Error(UNINITIALISED_MODULE_ERROR);
} }
if (!TOKENIZERS.includes(tokenizer)) { if (!TOKENIZERS.includes(tokenizer)) {
throw new Error(UNSUPPORTED_TOKENIZER_ERROR); throw new Error(UNSUPPORTED_TOKENIZER_ERROR);
} }
const leftCursor = toWasmTextWithCursors(left); const leftCursor = toWasmTextWithCursors(left);
const rightCursor = toWasmTextWithCursors(right); const rightCursor = toWasmTextWithCursors(right);
const result = wasmReconcileWithHistory( const result = wasmReconcileWithHistory(original, leftCursor, rightCursor, tokenizer);
original,
leftCursor,
rightCursor,
tokenizer
);
leftCursor.free(); leftCursor.free();
rightCursor.free(); rightCursor.free();
const jsResult = toTextWithCursors(result); const jsResult = toTextWithCursors(result);
const history = result.history().map(toSpanWithHistory); const history = result.history().map(toSpanWithHistory);
result.free(); result.free();
return { return {
...jsResult, ...jsResult,
history, history,
}; };
} }
function toWasmTextWithCursors( function toWasmTextWithCursors(text: string | TextWithCursors): wasmTextWithCursors {
text: string | TextWithCursors const isInputString = typeof text == 'string';
): wasmTextWithCursors { const leftText = isInputString ? text : text.text;
const isInputString = typeof text == "string"; const leftCursors = isInputString ? [] : (text.cursors ?? []);
const leftText = isInputString ? text : text.text;
const leftCursors = isInputString ? [] : text.cursors ?? [];
return new wasmTextWithCursors( return new wasmTextWithCursors(leftText, leftCursors.map(toWasmCursorPosition));
leftText,
leftCursors.map(toWasmCursorPosition)
);
} }
function toWasmCursorPosition({ function toWasmCursorPosition({ id, position }: CursorPosition): wasmCursorPosition {
id, return new wasmCursorPosition(id, position);
position,
}: CursorPosition): wasmCursorPosition {
return new wasmCursorPosition(id, position);
} }
function toTextWithCursors( function toTextWithCursors(textWithCursor: wasmTextWithCursors): TextWithCursors {
textWithCursor: wasmTextWithCursors return {
): TextWithCursors { text: textWithCursor.text(),
return { cursors: textWithCursor.cursors().map(toCursorPosition),
text: textWithCursor.text(), };
cursors: textWithCursor.cursors().map(toCursorPosition),
};
} }
function toCursorPosition(cursor: wasmCursorPosition): CursorPosition { function toCursorPosition(cursor: wasmCursorPosition): CursorPosition {
return { return {
id: cursor.id(), id: cursor.id(),
position: cursor.characterIndex(), position: cursor.characterIndex(),
}; };
} }
function toSpanWithHistory( function toSpanWithHistory(textWithHistory: wasmSpanWithHistory): SpanWithHistory {
textWithHistory: wasmSpanWithHistory return {
): SpanWithHistory { text: textWithHistory.text(),
return { history: textWithHistory.history(),
text: textWithHistory.text(), };
history: textWithHistory.history(),
};
} }

View file

@ -1,19 +1,17 @@
{ {
"compilerOptions": { "compilerOptions": {
"module": "ESNext", "module": "ESNext",
"target": "ESNext", "target": "ESNext",
"strict": true, "strict": true,
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"esModuleInterop": true, "esModuleInterop": true,
"moduleResolution": "bundler", "moduleResolution": "bundler",
"declaration": true, "declaration": true,
"declarationDir": "./dist/types", "declarationDir": "./dist/types",
"outDir": "./dist", "outDir": "./dist",
"rootDir": "./src", "rootDir": "./src",
"skipLibCheck": true, "skipLibCheck": true,
"inlineSourceMap": true "inlineSourceMap": true
}, },
"exclude": [ "exclude": ["./dist"]
"./dist" }
]
}

View file

@ -5,4 +5,10 @@ set -e
cargo clippy --all-targets --all-features --fix --allow-dirty --allow-staged cargo clippy --all-targets --all-features --fix --allow-dirty --allow-staged
cargo fmt --all cargo fmt --all
echo "Success!" cd reconcile-js
npm run format
cd ../examples/website
npm run format
echo "Success!"