chore: Check types.

Enabling type checking involves a full rearrangement of the
  build process, as well as supplying types for some of the
  packages. The X_ITE types are still a work in progress, but
  they are enough for this initial state of the project to
  compile and run.

  Resolves #14.
This commit is contained in:
Glen Whitney 2023-09-05 23:20:17 -07:00
parent a8707386aa
commit 6bcec494e2
15 changed files with 736 additions and 32 deletions

2
.gitignore vendored
View File

@ -1,4 +1,6 @@
# Object files # Object files
tsbuild
jsbuild
public/js public/js
# Editor backups # Editor backups

5
etc/depPreamble.text Normal file
View File

@ -0,0 +1,5 @@
// This source file was replicated from the netless GitHub repository
// https://github.com/netless-io/netless-app
// compliant with the MIT License, under which it was released.
// The authors of archematics wish to express their thanks to the
// netless team for creating and releasing this code.

382
etc/deps/geogebra/api.ts Normal file
View File

@ -0,0 +1,382 @@
// This source file was replicated from the netless GitHub repository
// https://github.com/netless-io/netless-app
// compliant with the MIT License, under which it was released.
// The authors of archematics wish to express their thanks to the
// netless team for creating and releasing this code.
/**
* @link https://wiki.geogebra.org/en/Reference:GeoGebra_Apps_API
*/
export interface AppletObject {
remove(): void;
getXML(objName?: string): string;
getAlgorithmXML(objName: string): string;
getPerspectiveXML(): string;
getBase64: {
(callback?: (base64string: string) => void): string;
(includeThumbnail?: boolean, callback?: (base64string: string) => void): string;
};
setBase64(base64string: string, callback: () => void): void;
openFile(filename: string, callback: () => void): void;
login(token: string, ui: boolean): void;
logout(): void;
setXML(xml: string): void;
evalXML(xmlString: string): void;
setDisplayStyle(objName: string, style: string): void;
evalCommand(cmdString: string): boolean;
evalCommandGetLabels(cmdString: string): string;
asyncEvalCommand(cmdString: string): Promise<string>;
asyncEvalCommandGetLabels(cmdString: string): Promise<string>;
evalCommandCAS(cmdString: string): string;
evalGeoGebraCAS(cmdString: string): string;
setFixed(objName: string, flag: boolean, selection?: boolean): void;
isFixed(objName: string): boolean;
isSelectionAllowed(objName: string): boolean;
setOnTheFlyPointCreationActive(flag: boolean): void;
setUndoPoint(): void;
setSaved(): void;
isSaved(): boolean;
startSaveCallback(title: string, visibility: string, callbackAction: string): void;
initCAS(): void;
setErrorDialogsActive(flag: boolean): void;
setCoordSystem(xmin: number, xmax: number, ymin: number, ymax: number, zmin?: number, zmax?: number, yVertical?: boolean): void;
reset(): void;
refreshViews(): void;
setVisible(objName: string, visible: boolean): void;
getVisible(objName: string, view?: number): boolean;
setLayer(objName: string, layer: number): void;
getLayer(objName: string): number;
setLayerVisible(layer: number, visible: boolean): void;
setTrace(objName: string, flag: boolean): void;
isTracing(objName: string): boolean;
setLabelVisible(objName: string, visible: boolean): void;
setLabelStyle(objName: string, style: number): void;
getLabelStyle(objName: string): number;
getLabelVisible(objName: string): boolean;
setColor(objName: string, red: number, green: number, blue: number): void;
setCorner(objName: string, x: number, y: number, index?: number): void;
setLineStyle(objName: string, style: number): void;
setLineThickness(objName: string, thickness: number): void;
setPointStyle(objName: string, style: number): void;
setPointSize(objName: string, style: number): void;
setFilling(objName: string, filling: number): void;
getColor(objName: string): string;
getPenColor(): string;
getPenSize(): number;
setPenSize(size: number): void;
setPenColor(red: number, green: number, blue: number): void;
getFilling(objName: string): number;
getImageFileName(objName: string): string;
getLineStyle(objName: string): number;
getLineThickness(objName: string): number;
getPointStyle(objName: string): number;
getPointSize(objName: string): number;
deleteObject(objName: string): void;
setAnimating(objName: string, animate: boolean): void;
setAnimationSpeed(objName: string, speed: number): void;
startAnimation(): void;
stopAnimation(): void;
setAuxiliary(objName: string, auxiliary: boolean): void;
hideCursorWhenDragging(hideCursorWhenDragging: boolean): void;
isAnimationRunning(): boolean;
getFrameRate(): number;
renameObject(oldName: string, newName: string, force?: boolean): boolean;
exists(objName: string): boolean;
isDefined(objName: string): boolean;
getValueString(objName: string, localized?: boolean): string;
getListValue(objName: string, index: number): number;
getDefinitionString(objName: string, localized?: boolean): string;
getLaTeXString(objName: string): string;
getLaTeXBase64(objName: string, value: boolean): string;
getCommandString(objName: string, localized?: boolean): string;
getCaption(objName: string, subst?: boolean): string;
setCaption(objName: string, caption: string): void;
getXcoord(objName: string): number;
getYcoord(objName: string): number;
getZcoord(objName: string): number;
setCoords(objName: string, x: number, y: number, z: number): void;
getValue(objName: string): number;
getVersion(): string;
getScreenshotBase64(callback: (data: string) => void, scale?: number): void;
getThumbnailBase64(): string;
setValue(objName: string, x: number): void;
setTextValue(objName: string, x: string): void;
setListValue(objName: string, x: number | boolean, y: number | boolean): void;
setRepaintingActive(flag: boolean): void;
setAxesVisible: {
(x: boolean, y: boolean): void;
(view: number, x: boolean, y: boolean, z: boolean): void;
};
setAxisUnits(view: number, x: string, y: string, z: string): void;
setAxisLabels(view: number, x: string, y: string, z: string): void;
setAxisSteps(view: number, x: string, y: string, z: string): void;
getAxisUnits(view: number): string[];
getAxisLabels(view: number): string[];
setPointCapture(view: number, capture?: number): void;
getGridVisible(view?: number): boolean;
setGridVisible: {
(visible: boolean): void;
(view: number, visible?: boolean): void;
};
getAllObjectNames(objectType?: string): string[];
getObjectNumber(): number;
getObjectName(i: number): string;
getObjectType(objName: string): string;
setMode(mode: number): void;
getMode(): number;
getToolName(i: number): string;
openMaterial(material: string): void;
undo(): void;
redo(): void;
newConstruction(): void;
resetAfterSaveLoginCallbacks(): void;
debug(str: string): void;
setWidth(width: number): void;
setHeight(height: number): void;
setSize(width: number, height: number): void;
enableRightClick(enable: boolean): void;
enableLabelDrags(enable: boolean): void;
enableShiftDragZoom(enable: boolean): void;
showToolBar(show: boolean): void;
setCustomToolBar(toolbarDef: string): void;
showMenuBar(show: boolean): void;
showAlgebraInput(show: boolean): void;
showResetIcon(show: boolean): void;
getViewProperties(view: number): string;
setFont(label: string, size: number, bold: boolean, italic: boolean, serif: boolean): void;
insertImage(url: string, corner1: string, corner2: string, corner4: string): string;
addImage(fileName: string, urlOrSvgContent: string): void;
recalculateEnvironments(): void;
isIndependent(label: string): boolean;
isMoveable(label: string): boolean;
setPerspective(code: string): void;
enableCAS(enable: boolean): void;
enable3D(enable: boolean): void;
getFileJSON(thumbnail?: boolean): { archive: { fileName: string; fileContent: string }[] };
setFileJSON(zip: { archive: { fileName: string; fileContent: string }[] }): void;
setLanguage(lang: string): void;
showTooltip(tooltip: boolean): void;
addMultiuserSelection(
clientId: string,
name: string,
color: string,
label: string,
newGeo: boolean
): void;
removeMultiuserSelections(clientId: string): void;
getExerciseFraction(): number;
isExercise(): boolean;
setExternalPath(path: string): void;
checkSaved(path: () => void): void;
getCASObjectNumber(): number;
exportPGF(callback: (data: string) => void): void;
exportSVG: {
(filename: string): void;
(callback: (svg: string) => void): void;
};
exportPDF: {
(scale: number, filename: string, sliderLabel: string): void;
(scale: number, callback: (pdf: string) => void, sliderLabel: string): void;
};
exportPSTricks(callback: (data: string) => void): void;
exportAsymptote(callback: (data: string) => void): void;
setRounding(digits: string): void;
getRounding(): string;
copyTextToClipboard(text: string): void;
evalLaTeX(text: string, mode: number): void;
evalMathML(text: string): boolean;
getScreenReaderOutput(text: string): string;
getEditorState(): string;
setEditorState(state: string, label: string): void;
getGraphicsOptions(viewId: number): GraphicsOptions;
setGraphicsOptions(viewId: number, options: string | RecursivePartial<GraphicsOptions>): void;
translate(arg1: string, callback: (data: string) => void): string;
exportConstruction(flags: string[]): string;
updateConstruction(): void;
getConstructionSteps(breakpoints?: boolean): number;
setConstructionStep(n: number, breakpoints?: boolean): void;
previousConstructionStep(): void;
nextConstructionStep(): void;
getEmbeddedCalculators(includeGraspableMath?: boolean): Record<string, AppletObject>;
getFrame(): HTMLElement;
enableFpsMeasurement(): void;
disableFpsMeasurement(): void;
testDraw(): void;
startDrawRecording(): void;
endDrawRecordingAndLogResults(): void;
registerAddListener(JSFunctionName: string | ((objName: string) => void)): void;
unregisterAddListener(JSFunctionName: string | ((objName: string) => void)): void;
registerStoreUndoListener(JSFunctionName: string | (() => void)): void;
unregisterStoreUndoListener(JSFunctionName: string | (() => void)): void;
registerRemoveListener(JSFunctionName: string | ((objName: string) => void)): void;
unregisterRemoveListener(JSFunctionName: string | ((objName: string) => void)): void;
registerClearListener(JSFunctionName: string | (() => void)): void;
unregisterClearListener(JSFunctionName: string | (() => void)): void;
registerRenameListener(
JSFunctionName: string | ((oldName: string, newName: string) => void)
): void;
unregisterRenameListener(
JSFunctionName: string | ((oldName: string, newName: string) => void)
): void;
registerUpdateListener(JSFunctionName: string | ((objName: string) => void)): void;
unregisterUpdateListener(JSFunctionName: string | ((objName: string) => void)): void;
registerClientListener(JSFunctionName: string | ((event: ClientEvent) => void)): void;
unregisterClientListener(JSFunctionName: string | ((event: ClientEvent) => void)): void;
registerObjectUpdateListener(
objName: string,
JSFunctionName: string | ((objName: string) => void)
): void;
unregisterObjectUpdateListener(objName: string): void;
registerObjectClickListener(objName: string, JSFunctionName: string | (() => void)): void;
unregisterObjectClickListener(objName: string): void;
registerClickListener(JSFunctionName: string | ((objName: string) => void)): void;
unregisterClickListener(JSFunctionName: string | ((objName: string) => void)): void;
handleSlideAction(eventType: string, pageIdx: string, appState?: string): void;
selectSlide(pageIdx: string): void;
updateOrdering(labels: string): void;
previewRefresh(): void;
groupObjects(objects: string[]): void;
ungroupObjects(objects: string[]): void;
getObjectsOfItsGroup(object: string): string[];
addToGroup(item: string, objectsInGroup: string[]): void;
setEmbedContent(label: string, base64: string): void;
addGeoToTV(label: string): void;
removeGeoFromTV(label: string): void;
setValuesOfTV(values: string): void;
showPointsTV(column: string, show: string): void;
hasUnlabeledPredecessors(label: string): boolean;
lockTextElement(label: string): void;
unlockTextElement(label: string): void;
}
export type AxisConfiguration = {
label: string | null,
unitLabel: string | null,
positiveAxis: boolean,
showNumbers: boolean,
tickStyle: number,
visible: boolean
}
export type AxesConfiguration = {
x: AxisConfiguration,
y: AxisConfiguration,
z: AxisConfiguration
}
export type GraphicsOptions = {
axesColor: string,
bgColor: string,
gridColor: string,
axes: AxesConfiguration,
grid: boolean,
gridDistance: {x: number | null, y: number | null},
gridType: number,
pointCapturing: number,
rightAngleStyle: number,
rulerType: number
}
type RecursivePartial<T> = {
[P in keyof T]?: RecursivePartial<T[P]>;
};
/**
* @link https://wiki.geogebra.org/en/Reference:GeoGebra_Apps_API#Client_Events
*/
export type ClientEvent =
// when new macro is added, `argument`: macro name
| { type: "addMacro"; argument: string }
// polygon construction started
| { type: "addPolygon" }
// polygon construction finished, `target`: polygon label
| { type: "addPolygonComplete"; target: string }
// Graphing / Geometry apps: algebra tab selected in sidebar
| { type: "algebraPanelSelected" }
// multiple objects deleted
| { type: "deleteGeos" }
// one or all objects removed from selection, `target`: object name (for single object) or null (deselect all)
| { type: "deselect"; target: string | null }
// mouse drag ended
| { type: "dragEnd" }
// dropdown list closed, `target`: dropdown list name, `index` index of selected item (0 based) */
| { type: "dropdownClosed"; target: string; index: number }
// dropdown list item focused using mouse or keyboard, `target`: dropdown list name, `index` index of focused item (0 based) */
| { type: "dropdownItemFocused"; target: string; index: number }
// dropdown list opened, `target`: dropdown list name
| { type: "dropdownOpened"; target: string }
// key typed in editor (Algebra view of any app or standalone Evaluator app),
| { type: "editorKeyTyped" }
// user moves focus to the editor (Algebra view of any app or standalone Evaluator app), `target:` object label if editing existing object
| { type: "editorStart"; target?: string }
// user (Algebra view of any app or standalone Evaluator app), `target`: object label if editing existing object
| { type: "editorStop"; target?: string }
// export started, `argument`: JSON encoded array including export format
| { type: "export"; argument: string }
// user pressed the mouse button, `x`: mouse x-coordinate, `y`: mouse y-coordinate
| { type: "mouseDown"; x: number; y: number }
// multiple objects move ended, `argument`: object labels
| { type: "movedGeos"; argument: string[] }
// multiple objects are being moved, `argument`: object labels
| { type: "movingGeos"; argument: string[] }
// dialog is opened (currently just for export dialog), `argument`: dialog ID
| { type: "openDialog"; argument: string }
// main menu or one of its submenus were open, `argument`: submenu ID
| { type: "openMenu"; argument: string }
// pasting multiple objects started, `argument`: pasted objects as XML
| { type: "pasteElms"; argument: string }
// pasting multiple objects ended,
| { type: "pasteElmsComplete" }
// perspective changed (e.g. a view was opened or closed),
| { type: "perspectiveChange" }
// redo button pressed,
| { type: "redo" }
// relation tool used, `argument`: HTML description of the object relation
| { type: "relationTool"; argument: string }
// custom tool removed, `argument`: custom tool name
| { type: "removeMacro"; argument: string }
// object renaming complete (in case of chain renames),
| { type: "renameComplete" }
// custom tool was renamed, `argument`: array [old name, new name]
| { type: "renameMacro"; argument: [oldName: string, newName: string] }
// object added to selection, `target`: object label
| { type: "select"; target: string }
// app mode changed (e.g. a tool was selected), `argument`: mode number (see toolbar reference for details)
| { type: "setMode"; argument: string }
// navigation bar visibility changed, `argument`: "true" or "false"
| { type: "showNavigationBar"; argument: string }
// style bar visibility changed, `argument`: "true" or "false"
| { type: "showStyleBar"; argument: string }
// side panel (where algebra view is in Graphing Calculator) closed,
| { type: "sidePanelClosed" }
// side panel (where algebra view is in Graphing Calculator) opened,
| { type: "sidePanelOpened" }
// table of values panel selected,
| { type: "tablePanelSelected" }
// tools panel selected,
| { type: "toolsPanelSelected" }
// undo pressed,
| { type: "undo" }
// object style changed, `target`: object label
| { type: "updateStyle"; target: string }
// graphics view dimensions changed by zooming or panning, `xZero`: horizontal pixel position of point (0,0), `yZero`: vertical pixel position of point (0,0), `xscale`: ratio pixels / horizontal units, `yscale`: ratio pixels / vertical units, `viewNo`: graphics view number (1 or 2)
| {
type: "viewChanged2D";
xZero: number;
yZero: number;
scale: number;
yscale: number;
viewNo: 1 | 2;
}
// 3D view dimensions changed by zooming or panning, similar to 2D, e.g. `xZero: 0,yZero: 0,scale: 50,yscale: 50,viewNo: 512,zZero: -1.5,zscale: 50,xAngle: -40,zAngle: 24`
| {
type: "viewChanged3D";
xZero: number;
yZero: number;
zZero: number;
scale: number;
yscale: number;
zscale: number;
xAngle: number;
zAngle: number;
viewNo: 1 | 2;
};

View File

@ -0,0 +1,76 @@
// This source file was replicated from the netless GitHub repository
// https://github.com/netless-io/netless-app
// compliant with the MIT License, under which it was released.
// The authors of archematics wish to express their thanks to the
// netless team for creating and releasing this code.
import type { AppletObject } from "./api";
import type { AppletParameters } from "./params";
export type AppletType = "preferJava" | "preferHTML5" | "java" | "html5" | "auto" | "screenshot";
export type Views = Record<
"is3D" | "AV" | "SV" | "CV" | "EV2" | "CP" | "PC" | "DA" | "FI" | "PV" | "macro",
boolean
>;
export type GGBAppletParameters = AppletParameters & {
material_id?: string;
appletOnLoad?: (api: AppletObject) => void;
};
export declare class GGBApplet {
constructor(
version?: number | string,
parameters?: GGBAppletParameters,
html5NoWebSimple?: boolean
);
constructor(parameters?: GGBAppletParameters, html5NoWebSimple?: boolean);
/**
* Overrides the codebase for HTML5.
* @param codebase Can be an URL or a local file path.
* @param offline Set to true, if the codebase is a local URL and no web URL
*/
setHTML5Codebase(codebase: string, offline?: boolean): void;
/** @deprecated not supported */
setJavaCodebase(): void;
/** @deprecated not supported */
setJavaCodebaseVersion(): void;
/** @deprecated not supported */
isCompiledInstalled(): void;
/** @deprecated not supported */
setPreCompiledScriptPath(): void;
/** @deprecated not supported */
setPreCompiledResourcePath(): void;
/**
* Overrides the codebase version for HTML5.
* If another codebase than the default codebase should be used, this method has to be called before setHTML5Codebase.
* @param version The version of the codebase that should be used for HTML5 applets.
*/
setHTML5CodebaseVersion(version: number | string, offline?: boolean): void;
getHTML5CodebaseVersion(): string;
getParameters(): GGBAppletParameters | undefined;
setFontsCSSURL(url: string): void;
inject(containerID: string | HTMLElement, type?: AppletType, noPreview?: boolean): void;
inject(containerID: string | HTMLElement, noPreview?: boolean): void;
getViews(): Views | null;
isJavaInstalled(): false;
isHTML5Installed(): true;
getLoadedAppletType(): AppletType | null;
setPreviewImage(previewFilePath: string, loadingFilePath: string, playFilePath: string): void;
removeExistingApplet(appletParent: string, showScreenshot?: boolean): void;
refreshHitPoints(): boolean;
startAnimation(): boolean;
stopAnimation(): boolean;
getAppletObject(): AppletObject | undefined;
resize(): void;
}

160
etc/deps/geogebra/params.ts Normal file
View File

@ -0,0 +1,160 @@
// This source file was replicated from the netless GitHub repository
// https://github.com/netless-io/netless-app
// compliant with the MIT License, under which it was released.
// The authors of archematics wish to express their thanks to the
// netless team for creating and releasing this code.
/**
* @link https://wiki.geogebra.org/en/Reference:GeoGebra_App_Parameters
*/
export interface AppletParameters {
/** @default "ggbApplet" */
id?: string;
/** @default "" */
filename?: string;
/** @default "" */
json?: string;
/** @default true */
enableLabelDrags?: boolean;
/** @default true */
enableUndoRedo?: boolean;
/** @default true */
enableRightClick?: boolean;
/** @default false */
enableCAS?: boolean;
/** @default false */
enable3D?: boolean;
/** @default false */
lockExam?: boolean;
/** @default "" */
rounding?: `${number}${"" | "s" | "r"}`;
/** @default "" */
ggbBase64?: string;
/** @default false */
showMenuBar?: boolean;
/** @default false */
showToolBar?: boolean;
/** @default true */
showToolBarHelp?: boolean;
/** @link https://wiki.geogebra.org/en/Reference:Toolbar @default "" */
customToolBar?: string;
/** @default false */
showAlgebraInput?: boolean;
/** @default "algebra" */
algebraInputPosition?: "algebra" | "top" | "bottom";
/** @default false */
showResetIcon?: boolean;
/** @default true */
showAnimationButton?: boolean;
/** @default 3 */
capturingThreshold?: number;
/** @link https://www.wikiwand.com/en/List_of_ISO_639-1_codes @default "" */
language?: string;
/** @default "" */
country?: string;
/** @default false */
useBrowserForJS?: boolean;
/** @default true */
enableShiftDragZoom?: boolean;
/** @default 0 */
width?: number;
/** @default 0 */
height?: number;
/** @default false */
fittoscreen?: boolean;
/** @default "" */
borderColor?: string;
/** @default false */
showLogging?: boolean;
/** @default true */
allowSymbolTable?: boolean;
/** @default false */
allowStyleBar?: boolean;
/** @default false */
app?: boolean;
/** @default false */
screenshotGenerator?: boolean;
/** @default "" */
laf?: string;
/** @default false */
preventFocus?: boolean;
/** @link https://wiki.geogebra.org/en/SetPerspective_Command @default "" */
perspective?: string;
/** @default "classic" */
appName?: "graphing" | "geometry" | "3d" | "classic" | "suite" | "evaluator" | "scientific";
/** @default 1.0 */
scale?: number;
/** @default false */
buttonShadows?: boolean;
/** @default 0.2 */
buttonRounding?: number;
/** @default "#000000" */
buttonBorderColor?: string;
/** @default false */
prerelease?: boolean;
/** @default "" */
tubeid?: string;
/** @default false */
showTutorialLink?: boolean;
/** @default true */
enableFileFeatures?: boolean;
/** @default true */
errorDialogsActive?: boolean;
/** @default false */
showAppsPicker?: boolean;
/** @default false */
showZoomButtons?: boolean;
/** @default false */
showFullscreenButton?: boolean;
/** @default false */
showSuggestionButtons?: boolean;
/** @default false */
showStartTooltip?: boolean;
/** @default 0 */
marginTop?: number;
/** @default -1 */
randomSeed?: number;
/** @default "" */
fontscssurl?: string;
/** @default "" */
scaleContainerClass?: string;
/** @default false */
allowUpscale?: boolean;
/** @default false */
playButton?: boolean;
/** @default false */
autoHeight?: boolean;
/** @default false */
disableAutoScale?: boolean;
/** @default true */
randomize?: boolean;
/** @default "" */
loginURL?: string;
/** @default "" */
logoutURL?: string;
/** @default "" */
backendURL?: string;
/** @default "" */
fullscreenContainer?: string;
/** @default "" */
shareLinkPrefix?: string;
/** @default "" */
vendor?: string;
/** @default 0 */
fontSize?: number;
/** @default undefined */
keyboardType?: "scientific" | "normal" | "notes";
/** @default false */
textMode?: boolean;
/** @default "white" */
editorBackgroundColor?: string;
/** @default "black" */
editorForegroundColor?: string;
/** @default false */
showSlides?: boolean;
/** @default false */
useLocalizedDigits?: boolean;
/** @default true */
useLocalizedPointNames?: boolean;
/** @default "undef" */
detachKeyboard?: string;
}

7
etc/deps/geogebraAmbient.d.ts vendored Normal file
View File

@ -0,0 +1,7 @@
// Hack to move GGBApplet into the global namespace
// (since we are getting it from a script)
import {GGBApplet as moduleGGBApplet} from './geogebra/entry.ts'
declare global {
class GGBApplet extends moduleGGBApplet {
}
}

16
etc/deps/x_ite.d.ts vendored Normal file
View File

@ -0,0 +1,16 @@
declare module 'https://create3000.github.io/code/x_ite/latest/x_ite.mjs' {
const x3d: X3D;
export default x3d;
export interface X3D {
createBrowser(): HTMLElement;
getBrowser(canvas: HTMLElement): X3DBrowser;
}
export interface X3DBrowser {
createX3DFromString(x3dSyntax: string): Promise<X3DScene>;
replaceWorld(scene: X3DScene): Promise<void>;
}
export interface X3DScene {
removeExportedNode(exportedName: string): void;
}
}

View File

@ -4,12 +4,21 @@
description: 'Uncovering lost digital mathematical treasures', description: 'Uncovering lost digital mathematical treasures',
scripts: { scripts: {
test: 'echo "Error: no test specified" && exit 1', test: 'echo "Error: no test specified" && exit 1',
build_js: 'civet --js -c src/*.civet -o public/js/.js', // Obtain additional source code needed:
build_deps: 'cp -rLT node_modules/vrml1to97 public/js/deps', prebuild: 'bash tools/fetchDeps.bash',
// Use civet to create .ts files from the source...
build_ts1: 'mkdir -p tsbuild && civet -c -o tsbuild/.ts src/*.civet',
// ... but also grab other existing files:
build_ts2: 'cp -r etc/deps tsbuild',
build_ts3: 'bash tools/copyDeps.bash tsbuild/deps',
// Use the Typescript compiler to create the final .js files:
build_js: 'tsc && mkdir -p public/js && cp -r jsbuild/* public/js',
build_deps: 'bash tools/copyDeps.bash public/js/deps',
build: 'pnpm --sequential /build_/', build: 'pnpm --sequential /build_/',
start: 'node public/js', start: 'node public/js',
go: 'pnpm --sequential "/build|start/"', go: 'pnpm --sequential "/build|start/"',
serve: 'pnpm build && http-server', serve: 'pnpm build && http-server',
clean: 'rm -rf tsbuild jsbuild public/js',
}, },
packageManager: 'pnpm', packageManager: 'pnpm',
keywords: [ keywords: [
@ -25,7 +34,9 @@
}, },
devDependencies: { devDependencies: {
'@danielx/civet': '^0.6.31', '@danielx/civet': '^0.6.31',
'@types/jquery': '^3.5.18',
'http-server': '^14.1.1', 'http-server': '^14.1.1',
typescript: '^5.2.2',
}, },
dependencies: { dependencies: {
vrml1to97: '^0.1.3', vrml1to97: '^0.1.3',

View File

@ -13,9 +13,15 @@ devDependencies:
'@danielx/civet': '@danielx/civet':
specifier: ^0.6.31 specifier: ^0.6.31
version: 0.6.31(typescript@5.2.2) version: 0.6.31(typescript@5.2.2)
'@types/jquery':
specifier: ^3.5.18
version: 3.5.18
http-server: http-server:
specifier: ^14.1.1 specifier: ^14.1.1
version: 14.1.1 version: 14.1.1
typescript:
specifier: ^5.2.2
version: 5.2.2
packages: packages:
@ -57,6 +63,16 @@ packages:
'@jridgewell/sourcemap-codec': 1.4.15 '@jridgewell/sourcemap-codec': 1.4.15
dev: true dev: true
/@types/jquery@3.5.18:
resolution: {integrity: sha512-sNm7O6LECFhHmF+3KYo6QIl2fIbjlPYa0PDgDQwfOaEJzwpK20Eub9Ke7VKkGsSJ2K0HUR50S266qYzRX4GlSw==}
dependencies:
'@types/sizzle': 2.3.3
dev: true
/@types/sizzle@2.3.3:
resolution: {integrity: sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==}
dev: true
/@typescript/vfs@1.5.0: /@typescript/vfs@1.5.0:
resolution: {integrity: sha512-AJS307bPgbsZZ9ggCT3wwpg3VbTKMFNHfaY/uF0ahSkYYrPF2dSSKDNIDIQAHm9qJqbLvCsSJH7yN4Vs/CsMMg==} resolution: {integrity: sha512-AJS307bPgbsZZ9ggCT3wwpg3VbTKMFNHfaY/uF0ahSkYYrPF2dSSKDNIDIQAHm9qJqbLvCsSJH7yN4Vs/CsMMg==}
dependencies: dependencies:

View File

@ -7,7 +7,7 @@
</head> </head>
<body> <body>
<p>Here is a <p>Here is a
<a href="http://127.0.0.1:8080/assets/hartWings.wrl">Hart polyhedron <a href="http://127.0.0.1:8080/assets/hartPoly.wrl">Hart polyhedron
</a>. </a>.
</p> </p>
</body> </body>

View File

@ -1,11 +1,19 @@
import https://code.jquery.com/jquery-3.7.1.js import https://code.jquery.com/jquery-3.7.1.js
import type {AppletObject} from ./deps/geogebra/api.ts
joyceApplets := [] type AppletDescription
html: string
children: HTMLCollection
id: string
width: number
height: number
joyceApplets: AppletDescription[] := []
$('applet[code="Geometry"]').before (i, html) -> $('applet[code="Geometry"]').before (i, html) ->
id := `joyceApplet${i}` id := `joyceApplet${i}`
joyceApplets.push { html, this.children, id, joyceApplets.push { html, this.children, id,
width: parseInt(this.getAttribute 'width'), width: parseInt(this.getAttribute('width') ?? '200'),
height: parseInt(this.getAttribute 'height') } height: parseInt(this.getAttribute('height') ?? '200') }
`<div id="${id}"></div>` `<div id="${id}"></div>`
jQuery.getScript 'https://www.geogebra.org/apps/deployggb.js', => jQuery.getScript 'https://www.geogebra.org/apps/deployggb.js', =>
@ -14,20 +22,25 @@ jQuery.getScript 'https://www.geogebra.org/apps/deployggb.js', =>
appName: 'classic', appName: 'classic',
jApp.width, jApp.width,
jApp.height, jApp.height,
appletOnLoad: (api) => appletOnLoad: (api: AppletObject) =>
for child of jApp.children for child of jApp.children
dispatchJcommand api, child dispatchJcommand api, child
api.setCoordSystem(-10, 10 + jApp.width, -10, 10 + jApp.height) api.setCoordSystem(-10, 10 + jApp.width, -10, 10 + jApp.height)
} } as const
geoApp := new GGBApplet params geoApp := new GGBApplet params
geoApp.inject jApp.id geoApp.inject jApp.id
type Cmdr type GeogebraCallback = (api: AppletObject) => void
type Commander
command: string command: string
callbacks: ((api) => boolean)[] callbacks: GeogebraCallback[]
function dispatchJcommand(api, param) type ClassHandler = (
name: string, m: string, data: string, colors: string[]) => Commander
function dispatchJcommand(api: AppletObject, param: Element): void
val := param.getAttribute 'value' val := param.getAttribute 'value'
unless val return
switch param.getAttribute 'name' switch param.getAttribute 'name'
'background' 'background'
api.setGraphicsOptions 1, bgColor: `#${val}` api.setGraphicsOptions 1, bgColor: `#${val}`
@ -48,39 +61,39 @@ function dispatchJcommand(api, param)
else else
console.log `Unkown param ${param}` console.log `Unkown param ${param}`
function jToG(jCom: string): Cmdr function jToG(jCom: string): Commander
[name, klass, method, data, ...colors] := jCom.split(';') [name, klass, method, data, ...colors] := jCom.split(';')
if klass in classHandler if klass in classHandler
return classHandler[klass] name, method, data, colors return classHandler[klass] name, method, data, colors
console.log `Unknown entity class ${klass}` console.log `Unknown entity class ${klass}`
return '' command: '', callbacks: []
classHandler := classHandler: Record<string, ClassHandler> :=
point: (name: string, m: string, data: string, colors: string[]): Cmdr => point: (name, method, data, colors) =>
command .= '' command .= ''
callbacks .= [] callbacks: GeogebraCallback[] .= []
switch m switch method
/free|fixed/ /free|fixed/
command += `${name} = (${data})` command += `${name} = (${data})`
if m is 'fixed' if method is 'fixed'
callbacks.push (api) => api.setFixed(name, true) callbacks.push (api: AppletObject) => api.setFixed(name, true)
'perpendicular' 'perpendicular'
[center, direction] := data.split(',') [center, direction] := data.split(',')
command += `${name} = Rotate(${direction}, 3*pi/2, ${center})` command += `${name} = Rotate(${direction}, 3*pi/2, ${center})`
return {command, callbacks} return {command, callbacks}
line: (name: string, m: string, data: string, colors: string[]): Cmdr => line: (name, method, data, colors) =>
command .= '' command .= ''
callbacks .= [] callbacks: GeogebraCallback[] .= []
switch m switch method
'connect' 'connect'
command += `${name} = Segment(${data})` command += `${name} = Segment(${data})`
return {command, callbacks} return {command, callbacks}
circle: (name: string, m: string, data: string, colors: string[]): Cmdr => circle: (name, method, data, colors) =>
command .= '' command .= ''
callbacks .= [] callbacks: GeogebraCallback[] .= []
switch m switch method
'radius' 'radius'
[center, point] := data.split(',') [center, point] := data.split(',')
command += `${name} = Circle(${center}, ${point})` command += `${name} = Circle(${center}, ${point})`

View File

@ -5,9 +5,9 @@ X3D from https://create3000.github.io/code/x_ite/latest/x_ite.mjs
certainlyHandled := '.x3d .gltf .glb .obj .stl .ply'.split ' ' certainlyHandled := '.x3d .gltf .glb .obj .stl .ply'.split ' '
canvas := X3D.createBrowser() canvas := X3D.createBrowser()
site := $('a[href^="http"]') site := $('a[href^="http"]')
url := site.attr 'href' url := site.attr('href') ?? ''
if certainlyHandled.some((ext) => url.includes ext) if certainlyHandled.some((ext) => url.includes ext)
canvas.setAttribute 'src', site.attr 'href' canvas.setAttribute 'src', url
else if url.includes '.wrl' else if url.includes '.wrl'
// Need to obtain the text and check what level it is // Need to obtain the text and check what level it is
response := await fetch url response := await fetch url

3
tools/copyDeps.bash Normal file
View File

@ -0,0 +1,3 @@
# Takes one parameter, the destination directory
mkdir -p $1
cp -rL node_modules/vrml1to97/{deps,vrml1to97,streamToString.js} $1

10
tools/fetchDeps.bash Normal file
View File

@ -0,0 +1,10 @@
mkdir -p etc/deps/geogebra
cp etc/depPreamble.text etc/deps/geogebra/api.ts
curl 'https://raw.githubusercontent.com/netless-io/netless-app/master/packages/app-geogebra/src/types/api.ts' >> etc/deps/geogebra/api.ts
cp etc/depPreamble.text etc/deps/geogebra/entry.ts
curl 'https://raw.githubusercontent.com/netless-io/netless-app/master/packages/app-geogebra/src/types/entry.ts' >> etc/deps/geogebra/entry.ts
cp etc/depPreamble.text etc/deps/geogebra/params.ts
curl 'https://raw.githubusercontent.com/netless-io/netless-app/master/packages/app-geogebra/src/types/params.ts' >> etc/deps/geogebra/params.ts

View File

@ -1,11 +1,14 @@
{ {
"compilerOptions": { "compilerOptions": {
"strict": true, "strict": true,
"lib": ["esnext"], "target": "esnext",
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"resolveJsonModule": true, "module": "esnext",
"esModuleInterop": true "esModuleInterop": true,
"rootDir": "tsbuild",
"outDir": "jsbuild",
}, },
"include": [ "tsbuild/**/*" ],
"ts-node": { "ts-node": {
"transpileOnly": true, "transpileOnly": true,
"compilerOptions": { "compilerOptions": {
@ -13,4 +16,4 @@
} }
} }
} }
}