diff --git a/.github/workflows/pages-deploy.yml b/.github/workflows/pages-deploy.yml index f8107dea7c..3ac0ae9821 100644 --- a/.github/workflows/pages-deploy.yml +++ b/.github/workflows/pages-deploy.yml @@ -36,7 +36,7 @@ jobs: run: cp -r src/java build - name: Deploy 🚀 - uses: peaceiris/actions-gh-pages@v3 + uses: peaceiris/actions-gh-pages@v4 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./build # The folder the action should deploy. diff --git a/.gitignore b/.gitignore index 9dc657cb09..bad059b581 100644 --- a/.gitignore +++ b/.gitignore @@ -47,3 +47,7 @@ scripts/bin.js .Trashes ehthumbs.db Thumbs.db + +# IDE # +####### +.idea/ diff --git a/.gitmodules b/.gitmodules index c1655131a5..f8c2f28716 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "src/java/java-packages"] path = src/java/java-packages - url = https://github.com/source-academy/java-packages + url = ../../source-academy/java-packages.git diff --git a/.vscode/settings.json b/.vscode/settings.json index df07be32fc..9ae728d458 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,4 @@ { "eslint.experimental.useFlatConfig": true, "files.eol": "\r\n", -} \ No newline at end of file +} diff --git a/devserver/README.md b/devserver/README.md index b43160729e..0107c4a8f2 100644 --- a/devserver/README.md +++ b/devserver/README.md @@ -2,4 +2,4 @@ This server relies on [`Vite`](https://vitejs.dev) to create a server that automatically reloads when it detects file system changes. This allows Source Academy developers to make changes to their tabs without having to use the frontend, and have it render code changes live. -The server is designed to be run using `yarn devserver` from the repository's root directory, hence `vite.config.ts` is not located within this folder. \ No newline at end of file +The server is designed to be run using `yarn devserver` from the repository's root directory, hence `vite.config.ts` is not located within this folder. diff --git a/devserver/index.html b/devserver/index.html index 840263ca9e..02cac35ad6 100644 --- a/devserver/index.html +++ b/devserver/index.html @@ -1,4 +1,4 @@ - + diff --git a/devserver/src/components/Playground.tsx b/devserver/src/components/Playground.tsx index 734d6a6335..1d7e2c6461 100644 --- a/devserver/src/components/Playground.tsx +++ b/devserver/src/components/Playground.tsx @@ -58,42 +58,41 @@ const Playground: React.FC<{}> = () => { } }; - const getAutoComplete = useCallback((row: number, col: number, callback: any) => { - getNames(editorValue, row, col, codeContext) - .then(([editorNames, displaySuggestions]) => { - if (!displaySuggestions) { - callback(); - return; - } - - const editorSuggestions = editorNames.map((editorName: any) => ({ - ...editorName, - caption: editorName.name, - value: editorName.name, - score: editorName.score ? editorName.score + 1000 : 1000, - name: undefined - })); - - const builtins: Record = SourceDocumentation.builtins[Chapter.SOURCE_4]; - const builtinSuggestions = Object.entries(builtins) - .map(([builtin, thing]) => ({ - ...thing, - caption: builtin, - value: builtin, - score: 100, - name: builtin, - docHTML: thing.description + const getAutoComplete = useCallback( + (row: number, col: number, callback: any) => { + getNames(editorValue, row, col, codeContext).then( + ([editorNames, displaySuggestions]) => { + if (!displaySuggestions) { + callback(); + return; + } + + const editorSuggestions = editorNames.map((editorName: any) => ({ + ...editorName, + caption: editorName.name, + value: editorName.name, + score: editorName.score ? editorName.score + 1000 : 1000, + name: undefined })); - callback(null, [ - ...builtinSuggestions, - ...editorSuggestions - ]); - }); - }, [editorValue, codeContext]); + const builtins: Record = SourceDocumentation.builtins[Chapter.SOURCE_4]; + const builtinSuggestions = Object.entries(builtins).map( + ([builtin, thing]) => ({ + ...thing, + caption: builtin, + value: builtin, + score: 100, + name: builtin, + docHTML: thing.description + }) + ); + + callback(null, [...builtinSuggestions, ...editorSuggestions]); + }); + }, [editorValue, codeContext]); const loadTabs = () => getDynamicTabs(codeContext) - .then((tabs) => { + .then(tabs => { setDynamicTabs(tabs); const newIds = tabs.map(({ id }) => id); @@ -104,7 +103,7 @@ const Playground: React.FC<{}> = () => { } setAlerts(newIds); }) - .catch((error) => { + .catch(error => { showToast(errorToast); console.log(error); }); @@ -115,7 +114,7 @@ const Playground: React.FC<{}> = () => { codeContext.moduleContexts = mockModuleContext.moduleContexts = {}; runInContext(editorValue, codeContext) - .then((result) => { + .then(result => { if (codeContext.errors.length > 0) { showToast(errorToast); } else { @@ -160,13 +159,8 @@ const Playground: React.FC<{}> = () => { controlBarProps: { editorButtons: [ , - , - + , + ] }, replProps: { @@ -184,16 +178,14 @@ const Playground: React.FC<{}> = () => { selectedTabId, onChange: useCallback((newId: string) => { setSelectedTab(newId); - setAlerts(alerts.filter((id) => id !== newId)); + setAlerts(alerts.filter(id => id !== newId)); }, [alerts]), alerts } }; return ( - + diff --git a/devserver/src/components/Workspace.tsx b/devserver/src/components/Workspace.tsx index 858f7a9f1c..af18450cb2 100644 --- a/devserver/src/components/Workspace.tsx +++ b/devserver/src/components/Workspace.tsx @@ -10,8 +10,8 @@ import { useDimensions } from './utils/Hooks'; type DispatchProps = { handleEditorEval: () => void; - handleEditorValueChange: (newValue: string) => void - handlePromptAutocomplete: (row: number, col: number, callback: any) => void + handleEditorValueChange: (newValue: string) => void; + handlePromptAutocomplete: (row: number, col: number, callback: any) => void; }; type StateProps = { @@ -21,9 +21,9 @@ type StateProps = { replProps: ReplProps; sideContentHeight?: number; sideContentIsResizeable?: boolean; - editorValue: string + editorValue: string; - sideContentProps: SideContentProps + sideContentProps: SideContentProps; }; const rightResizeOnly: Enable = { right: true }; @@ -31,7 +31,7 @@ const bottomResizeOnly: Enable = { bottom: true }; export type WorkspaceProps = DispatchProps & StateProps; -const Workspace: React.FC = (props) => { +const Workspace: React.FC = props => { const contentContainerDiv = React.useRef(null); const editorDividerDiv = React.useRef(null); const leftParentResizable = React.useRef(null); diff --git a/devserver/src/components/controlBar/ControlBar.tsx b/devserver/src/components/controlBar/ControlBar.tsx index 249cacc573..14c81360ef 100644 --- a/devserver/src/components/controlBar/ControlBar.tsx +++ b/devserver/src/components/controlBar/ControlBar.tsx @@ -8,7 +8,7 @@ export type ControlBarProps = { editingWorkspaceButtons?: Array; }; -const ControlBar: React.FC = (props) => { +const ControlBar: React.FC = props => { const editorControl = (
{props.editorButtons} @@ -16,7 +16,9 @@ const ControlBar: React.FC = (props) => { ); const flowControl = props.flowButtons && ( -
{props.flowButtons}
+
+ {props.flowButtons} +
); const editingWorkspaceControl = ( diff --git a/devserver/src/components/controlBar/ControlBarClearButton.tsx b/devserver/src/components/controlBar/ControlBarClearButton.tsx index adb04e941a..44ce463c15 100644 --- a/devserver/src/components/controlBar/ControlBarClearButton.tsx +++ b/devserver/src/components/controlBar/ControlBarClearButton.tsx @@ -3,13 +3,15 @@ import { IconNames } from '@blueprintjs/icons'; import ControlButton from '../ControlButton'; type Props = { - onClick: () => void + onClick: () => void; }; -export const ControlBarClearButton = (props: Props) => - -; +export const ControlBarClearButton = (props: Props) => ( + + + +); diff --git a/devserver/src/components/controlBar/ControlBarRefreshButton.tsx b/devserver/src/components/controlBar/ControlBarRefreshButton.tsx index f586b87441..5ee8edb2b8 100644 --- a/devserver/src/components/controlBar/ControlBarRefreshButton.tsx +++ b/devserver/src/components/controlBar/ControlBarRefreshButton.tsx @@ -3,13 +3,15 @@ import { IconNames } from '@blueprintjs/icons'; import ControlButton from '../ControlButton'; type Props = { - onClick: () => void + onClick: () => void; }; -export const ControlBarRefreshButton = (props: Props) => - -; +export const ControlBarRefreshButton = (props: Props) => ( + + + +); diff --git a/devserver/src/components/controlBar/ControlBarRunButton.tsx b/devserver/src/components/controlBar/ControlBarRunButton.tsx index e07163fd1b..a3600c013c 100644 --- a/devserver/src/components/controlBar/ControlBarRunButton.tsx +++ b/devserver/src/components/controlBar/ControlBarRunButton.tsx @@ -16,7 +16,7 @@ type StateProps = { type ControlButtonRunButtonProps = DispatchProps & StateProps; -export const ControlBarRunButton: React.FC = (props) => { +export const ControlBarRunButton: React.FC = props => { const tooltipContent = 'Evaluate the program'; return ( diff --git a/devserver/src/components/editor/Editor.tsx b/devserver/src/components/editor/Editor.tsx index 3bc31c9cc0..860480ab3a 100644 --- a/devserver/src/components/editor/Editor.tsx +++ b/devserver/src/components/editor/Editor.tsx @@ -28,8 +28,8 @@ type DispatchProps = { export type EditorStateProps = { newCursorPosition?: Position; - editorValue: string - handleEditorValueChange: (newCode: string) => void + editorValue: string; + handleEditorValueChange: (newCode: string) => void; }; export type EditorProps = DispatchProps & EditorStateProps; @@ -91,10 +91,9 @@ const Editor: React.FC = (props: EditorProps) => { // The () => ref.current() are designed to use the latest instance only. // Start autocompletion - acequire('ace/ext/language_tools') - .setCompleters([ - makeCompleter((...args) => handlePromptAutocompleteRef.current(...args)) - ]); + acequire('ace/ext/language_tools').setCompleters([ + makeCompleter((...args) => handlePromptAutocompleteRef.current(...args)) + ]); }, [editor]); React.useLayoutEffect(() => { diff --git a/devserver/src/components/repl/Repl.tsx b/devserver/src/components/repl/Repl.tsx index 60e8b5f713..c0118b44e4 100644 --- a/devserver/src/components/repl/Repl.tsx +++ b/devserver/src/components/repl/Repl.tsx @@ -19,7 +19,9 @@ const Output: React.FC = (props: OutputProps) => { case 'running': return ( -
{props.output.consoleLogs.join('\n')}
+
+            {props.output.consoleLogs.join('\n')}
+          
); case 'result': @@ -32,7 +34,9 @@ const Output: React.FC = (props: OutputProps) => { } return ( -
{props.output.consoleLogs.join('\n')}
+
+            {props.output.consoleLogs.join('\n')}
+          
{props.output.value}
); diff --git a/devserver/src/components/sideContent/SideContent.tsx b/devserver/src/components/sideContent/SideContent.tsx index 27125198f9..01acd221b3 100644 --- a/devserver/src/components/sideContent/SideContent.tsx +++ b/devserver/src/components/sideContent/SideContent.tsx @@ -21,11 +21,11 @@ export type SideContentProps = { renderActiveTabPanelOnly?: boolean; editorWidth?: string; sideContentHeight?: number; - dynamicTabs: SideContentTab[] + dynamicTabs: SideContentTab[]; - selectedTabId: string - alerts: string[] - onChange?: (newId: string, oldId: string) => void + selectedTabId: string; + alerts: string[]; + onChange?: (newId: string, oldId: string) => void; }; const renderTab = ( @@ -89,7 +89,7 @@ const SideContent: React.FC = ({ if (onChange) onChange(newId, oldId); }} > - {dynamicTabs.map((tab) => renderTab(tab, alerts.includes(tab.id), editorWidth, sideContentHeight))} + {dynamicTabs.map(tab => renderTab(tab, alerts.includes(tab.id), editorWidth, sideContentHeight))}
diff --git a/devserver/src/components/sideContent/TestTab.tsx b/devserver/src/components/sideContent/TestTab.tsx index cc1fcd0115..aa64ef6e82 100644 --- a/devserver/src/components/sideContent/TestTab.tsx +++ b/devserver/src/components/sideContent/TestTab.tsx @@ -1,26 +1,33 @@ import { IconNames } from '@blueprintjs/icons'; import type { SideContentTab } from './types'; -const TestTab = () =>
-

Source Academy Tab Development Server

-

- Run some code that imports modules in the editor on the left. You should see the corresponding module tab spawn.
- Whenever you make changes to the tab, the server should automatically reload and show the changes that you've made
- If that does not happen, you can click the refresh button to manually reload tabs -

-
; +const TestTab = () => ( +
+

Source Academy Tab Development Server

+

+ Run some code that imports modules in the editor on the left. You should + see the corresponding module tab spawn. +
+ Whenever you make changes to the tab, the server should automatically + reload and show the changes that you've made
+ If that does not happen, you can click the refresh button to manually + reload tabs +

+
+); const testTabContent: SideContentTab = { id: 'test', label: 'Welcome to the tab development server!', iconName: IconNames.LabTest, - body: + body: }; export default testTabContent; diff --git a/devserver/src/components/sideContent/types.ts b/devserver/src/components/sideContent/types.ts index c9108f5f31..b4891a7ce6 100644 --- a/devserver/src/components/sideContent/types.ts +++ b/devserver/src/components/sideContent/types.ts @@ -3,19 +3,19 @@ import type { Context } from 'js-slang'; import type { JSX } from 'react'; export type DebuggerContext = { - context: Context + context: Context; }; export type SideContentTab = { - id: string - label: string - iconName: IconName - body: JSX.Element + id: string; + label: string; + iconName: IconName; + body: JSX.Element; }; export type ModuleSideContent = { label: string; - iconName: IconName - toSpawn?: (context: DebuggerContext) => boolean - body: (context: DebuggerContext) => JSX.Element + iconName: IconName; + toSpawn?: (context: DebuggerContext) => boolean; + body: (context: DebuggerContext) => JSX.Element; }; diff --git a/devserver/src/components/sideContent/utils.ts b/devserver/src/components/sideContent/utils.ts index c6e5529fe6..f561f3089f 100644 --- a/devserver/src/components/sideContent/utils.ts +++ b/devserver/src/components/sideContent/utils.ts @@ -5,13 +5,16 @@ import type { ModuleSideContent, SideContentTab } from './types'; const moduleManifest = manifest as Record; export const getDynamicTabs = async (context: Context) => { - const moduleSideContents = await Promise.all(Object.keys(context.moduleContexts) - .flatMap((moduleName) => moduleManifest[moduleName].tabs.map(async (tabName) => { - const { default: rawTab } = await import(`../../../../src/tabs/${tabName}/index.tsx`); - return rawTab as ModuleSideContent; - }))); + const moduleSideContents = await Promise.all( + Object.keys(context.moduleContexts) + .flatMap(moduleName => moduleManifest[moduleName].tabs.map(async tabName => { + const { default: rawTab } = await import(`../../../../src/tabs/${tabName}/index.tsx`); + return rawTab as ModuleSideContent; + })) + ); - return moduleSideContents.filter(({ toSpawn }) => !toSpawn || toSpawn({ context })) + return moduleSideContents + .filter(({ toSpawn }) => !toSpawn || toSpawn({ context })) .map((tab): SideContentTab => ({ ...tab, // In the frontend, module tabs use their labels as IDs diff --git a/devserver/src/components/utils/AceHelper.ts b/devserver/src/components/utils/AceHelper.ts index 770e07a92f..336b2ba41c 100644 --- a/devserver/src/components/utils/AceHelper.ts +++ b/devserver/src/components/utils/AceHelper.ts @@ -16,8 +16,8 @@ export const selectMode = () => { const library = ''; if ( - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-expect-error + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-expect-error typeof ace.define.modules[`ace/mode/${getModeString(chapter, variant, library)}`]?.Mode === 'function' ) { diff --git a/devserver/src/main.tsx b/devserver/src/main.tsx index 38c8f70447..771c8bbb5a 100644 --- a/devserver/src/main.tsx +++ b/devserver/src/main.tsx @@ -4,10 +4,13 @@ import ReactDOM from 'react-dom'; import './styles/index.scss'; import Playground from './components/Playground'; -ReactDOM.render( -
-
- +ReactDOM.render( + +
+
+ +
-
-, document.getElementById('root')!); + , + document.getElementById('root')! +); diff --git a/eslint.config.js b/eslint.config.js index 4ee15bbce5..c779b2987c 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -58,11 +58,17 @@ export default [ '@stylistic/no-trailing-spaces': 'warn', '@stylistic/quotes': ['warn', 'single', { avoidEscape: true }], '@stylistic/semi': ['warn', 'always'], + '@stylistic/member-delimiter-style': 'error', '@stylistic/spaced-comment': [ 'warn', 'always', { markers: todoTreeKeywordsAll } ], + '@stylistic/arrow-parens': ['warn', 'as-needed'], + '@stylistic/operator-linebreak': ['warn', 'before'], + }, + linterOptions: { + reportUnusedDisableDirectives: 'warn' } }, ...tseslint.configs.recommended, @@ -133,8 +139,6 @@ export default [ 'import/extensions': ['error', 'never', { json: 'always' }], 'no-constant-condition': 'off', // Was 'error', - '@stylistic/arrow-parens': ['warn', 'as-needed'], - '@typescript-eslint/prefer-readonly': 'warn', '@typescript-eslint/require-await': 'error', '@typescript-eslint/return-await': ['error', 'in-try-catch'] diff --git a/modules.json b/modules.json index 914bd7bc80..b3e4139792 100644 --- a/modules.json +++ b/modules.json @@ -117,4 +117,4 @@ "Nbody" ] } -} \ No newline at end of file +} diff --git a/scripts/scripts_manager.js b/scripts/scripts_manager.js index 93c9d5e008..4b82ee9a47 100644 --- a/scripts/scripts_manager.js +++ b/scripts/scripts_manager.js @@ -59,16 +59,16 @@ const buildCommand = new Command('build') * @returns {Promise} */ function runJest(patterns) { - const [args, filePatterns] = _.partition(patterns ?? [], (arg) => arg.startsWith('-')); + const [args, filePatterns] = _.partition(patterns ?? [], arg => arg.startsWith('-')); // command.args automatically includes the source directory option // which is not supported by Jest, so we need to remove it - const toRemove = args.findIndex((arg) => arg.startsWith('--srcDir')); + const toRemove = args.findIndex(arg => arg.startsWith('--srcDir')); if (toRemove !== -1) { args.splice(toRemove, 1); } - const jestArgs = args.concat(filePatterns.map((pattern) => pattern.split(pathlib.win32.sep) + const jestArgs = args.concat(filePatterns.map(pattern => pattern.split(pathlib.win32.sep) .join(pathlib.posix.sep))); return jest.run(jestArgs, './scripts/jest.config.js'); diff --git a/scripts/src/build/__tests__/buildAll.test.ts b/scripts/src/build/__tests__/buildAll.test.ts index fc7ac69ed8..a516fd5b1f 100644 --- a/scripts/src/build/__tests__/buildAll.test.ts +++ b/scripts/src/build/__tests__/buildAll.test.ts @@ -12,8 +12,7 @@ jest.mock('../prebuild/lint'); jest.mock('../docs/docsUtils'); jest.mock('esbuild', () => ({ - build: jest.fn() - .mockResolvedValue({ outputFiles: [] }) + build: jest.fn().mockResolvedValue({ outputFiles: [] }) })); jest.spyOn(jsonModule, 'buildJsons'); @@ -22,62 +21,52 @@ jest.spyOn(tabsModule, 'bundleTabs'); jest.spyOn(bundleModule, 'bundleBundles'); const asMock = any>(func: T) => func as MockedFunction; -const runCommand = (...args: string[]) => getBuildAllCommand() - .parseAsync(args, { from: 'user' }); +const runCommand = (...args: string[]) => getBuildAllCommand().parseAsync(args, { from: 'user' }); describe('test build all command', () => { - testBuildCommand( - 'buildAll', - getBuildAllCommand, - [ - jsonModule.buildJsons, - htmlModule.buildHtml, - tabsModule.bundleTabs, - bundleModule.bundleBundles - ] - ); + testBuildCommand('buildAll', getBuildAllCommand, [ + jsonModule.buildJsons, + htmlModule.buildHtml, + tabsModule.bundleTabs, + bundleModule.bundleBundles + ]); it('should exit with code 1 if buildJsons returns with an error', async () => { - asMock(jsonModule.buildJsons) - .mockResolvedValueOnce({ - jsons: [{ + asMock(jsonModule.buildJsons).mockResolvedValueOnce({ + jsons: [ + { severity: 'error', name: 'test0', error: {} - }] - }); + } + ] + }); try { await runCommand(); } catch (error) { - expect(error) - .toEqual(new Error('process.exit called with 1')); + expect(error).toEqual(new Error('process.exit called with 1')); } - expect(process.exit) - .toHaveBeenCalledWith(1); + expect(process.exit).toHaveBeenCalledWith(1); }); it('should exit with code 1 if buildHtml returns with an error', async () => { - asMock(htmlModule.buildHtml) - .mockResolvedValueOnce({ - elapsed: 0, - result: { - severity: 'error', - error: {} - } - }); + asMock(htmlModule.buildHtml).mockResolvedValueOnce({ + elapsed: 0, + result: { + severity: 'error', + error: {} + } + }); try { await runCommand(); } catch (error) { - expect(error) - .toEqual(new Error('process.exit called with 1')); + expect(error).toEqual(new Error('process.exit called with 1')); } - expect(process.exit) - .toHaveBeenCalledWith(1); + expect(process.exit).toHaveBeenCalledWith(1); - expect(htmlModule.buildHtml) - .toHaveBeenCalledTimes(1); + expect(htmlModule.buildHtml).toHaveBeenCalledTimes(1); }); }); diff --git a/scripts/src/build/__tests__/buildUtils.test.ts b/scripts/src/build/__tests__/buildUtils.test.ts index dce466ea77..eb759e40c5 100644 --- a/scripts/src/build/__tests__/buildUtils.test.ts +++ b/scripts/src/build/__tests__/buildUtils.test.ts @@ -4,8 +4,8 @@ describe('Test retrieveBundlesAndTabs', () => { type TestCase = [ desc: string, { - bundles?: string[] | null - tabs?: string[] | null + bundles?: string[] | null; + tabs?: string[] | null; }, boolean, Awaited> diff --git a/scripts/src/build/docs/__mocks__/docsUtils.ts b/scripts/src/build/docs/__mocks__/docsUtils.ts index 8532cf4da5..e74da0b3d2 100644 --- a/scripts/src/build/docs/__mocks__/docsUtils.ts +++ b/scripts/src/build/docs/__mocks__/docsUtils.ts @@ -7,8 +7,7 @@ export const initTypedoc = jest.fn(() => { } as any; const app = { - convert: jest.fn() - .mockReturnValue(proj), + convert: jest.fn().mockReturnValue(proj), generateDocs: jest.fn(() => Promise.resolve()) }; diff --git a/scripts/src/build/docs/docsreadme.md b/scripts/src/build/docs/docsreadme.md index 0adf8f5beb..79538a4fdf 100644 --- a/scripts/src/build/docs/docsreadme.md +++ b/scripts/src/build/docs/docsreadme.md @@ -1,18 +1,23 @@ # Overview The Source Academy allows programmers to import functions and constants from a module, using JavaScript's `import` directive. For example, the programmer may decide to import the function `thrice` from the module `repeat` by starting the program with + ``` import { thrice } from "repeat"; ``` -When evaluating such a directive, the Source Academy looks for a module with the matching name, here `repeat`, in a preconfigured modules site. The Source Academy at https://sourceacademy.org uses the default modules site (located at https://source-academy.github.io/modules). +When evaluating such a directive, the Source Academy looks for a module with the matching name, here `repeat`, in a preconfigured modules site. The Source Academy at uses the default modules site (located at ). After importing functions or constants from a module, they can be used as usual. + ``` thrice(display)(8); // displays 8 three times ``` + if `thrice` is declared in the module `repeat` as follows: + ``` const thrice = f => x => f(f(f(x))); ``` -[List of modules](modules.html) available at the default modules site. \ No newline at end of file + +[List of modules](modules.html) available at the default modules site. diff --git a/scripts/src/build/docs/drawdown.ts b/scripts/src/build/docs/drawdown.ts index 8fe5d5aaa8..4efeeaf675 100644 --- a/scripts/src/build/docs/drawdown.ts +++ b/scripts/src/build/docs/drawdown.ts @@ -187,4 +187,4 @@ export default (src: string): string => { }); return src.trim(); -}; \ No newline at end of file +}; diff --git a/scripts/src/build/docs/html.ts b/scripts/src/build/docs/html.ts index 8594bed418..803afbf133 100644 --- a/scripts/src/build/docs/html.ts +++ b/scripts/src/build/docs/html.ts @@ -5,10 +5,10 @@ import type { AwaitedReturn } from '../utils'; import { initTypedoc, type TypedocResult } from './docsUtils'; export type HtmlResult = { - severity: 'error' | 'warn' - error: any + severity: 'error' | 'warn'; + error: any; } | { - severity: 'success' + severity: 'success'; }; export const buildHtml = wrapWithTimer(async ( diff --git a/scripts/src/build/modules/__tests__/bundle.test.ts b/scripts/src/build/modules/__tests__/bundle.test.ts index 817af39174..22a52031bb 100644 --- a/scripts/src/build/modules/__tests__/bundle.test.ts +++ b/scripts/src/build/modules/__tests__/bundle.test.ts @@ -5,28 +5,24 @@ import * as bundles from '../bundles'; jest.spyOn(bundles, 'bundleBundles'); jest.mock('esbuild', () => ({ - build: jest.fn() - .mockResolvedValue({ outputFiles: [] }) + build: jest.fn().mockResolvedValue({ outputFiles: [] }) })); -testBuildCommand( - 'buildBundles', - bundles.getBuildBundlesCommand, - [bundles.bundleBundles] -); +testBuildCommand('buildBundles', bundles.getBuildBundlesCommand, [ + bundles.bundleBundles +]); test('Normal command', async () => { - await bundles.getBuildBundlesCommand() + await bundles + .getBuildBundlesCommand() .parseAsync(['-b', 'test0'], { from: 'user' }); - expect(bundles.bundleBundles) - .toHaveBeenCalledTimes(1); + expect(bundles.bundleBundles).toHaveBeenCalledTimes(1); const [args] = (bundles.bundleBundles as MockedFunction).mock.calls[0]; - expect(args) - .toMatchObject({ - bundles: ['test0'], - tabs: ['tab0'], - modulesSpecified: true - }); + expect(args).toMatchObject({ + bundles: ['test0'], + tabs: ['tab0'], + modulesSpecified: true + }); }); diff --git a/scripts/src/build/modules/__tests__/streamMocker.ts b/scripts/src/build/modules/__tests__/streamMocker.ts index aab3c3e706..31595d4acd 100644 --- a/scripts/src/build/modules/__tests__/streamMocker.ts +++ b/scripts/src/build/modules/__tests__/streamMocker.ts @@ -2,7 +2,7 @@ import fs from 'fs/promises'; import { PassThrough } from 'stream'; import type { MockedFunction } from 'jest-mock'; -const mockedFsOpen = (fs.open as MockedFunction); +const mockedFsOpen = fs.open as MockedFunction; export function mockStream() { const stream = new PassThrough(); diff --git a/scripts/src/build/prebuild/__mocks__/lint.ts b/scripts/src/build/prebuild/__mocks__/lint.ts index eac3ba04fa..0ff31fee8b 100644 --- a/scripts/src/build/prebuild/__mocks__/lint.ts +++ b/scripts/src/build/prebuild/__mocks__/lint.ts @@ -1,10 +1,9 @@ -export const runEslint = jest.fn() - .mockImplementation(() => ({ - elapsed: 0, - result: { - formatted: '', - severity: 'error' - } - })); +export const runEslint = jest.fn().mockImplementation(() => ({ + elapsed: 0, + result: { + formatted: '', + severity: 'error' + } +})); export const eslintResultsLogger = jest.fn(() => ''); diff --git a/scripts/src/build/prebuild/__mocks__/tsc.ts b/scripts/src/build/prebuild/__mocks__/tsc.ts index 18f7fd9a6e..c58f4175ba 100644 --- a/scripts/src/build/prebuild/__mocks__/tsc.ts +++ b/scripts/src/build/prebuild/__mocks__/tsc.ts @@ -1,10 +1,9 @@ export const tscResultsLogger = jest.fn(() => ''); -export const runTsc = jest.fn() - .mockResolvedValue({ - elapsed: 0, - result: { - severity: 'error', - results: [] - } - }); +export const runTsc = jest.fn().mockResolvedValue({ + elapsed: 0, + result: { + severity: 'error', + results: [] + } +}); diff --git a/scripts/src/build/prebuild/__tests__/prebuild.test.ts b/scripts/src/build/prebuild/__tests__/prebuild.test.ts index 934883a486..12076a0c72 100644 --- a/scripts/src/build/prebuild/__tests__/prebuild.test.ts +++ b/scripts/src/build/prebuild/__tests__/prebuild.test.ts @@ -12,8 +12,7 @@ const mockedEslint = asMock(lintModule.runEslint); describe('test eslint command', () => { const runCommand = async (...args: string[]) => { - await lintModule.getLintCommand() - .parseAsync(args, { from: 'user' }); + await lintModule.getLintCommand().parseAsync(args, { from: 'user' }); }; test('regular command function', async () => { @@ -27,8 +26,7 @@ describe('test eslint command', () => { await runCommand(); - expect(lintModule.runEslint) - .toHaveBeenCalledTimes(1); + expect(lintModule.runEslint).toHaveBeenCalledTimes(1); }); it('should only lint specified bundles and tabs', async () => { @@ -42,16 +40,14 @@ describe('test eslint command', () => { await runCommand('-b', 'test0', '-t', 'tab0'); - expect(lintModule.runEslint) - .toHaveBeenCalledTimes(1); + expect(lintModule.runEslint).toHaveBeenCalledTimes(1); const [lintCall] = mockedEslint.mock.calls[0]; - expect(lintCall) - .toMatchObject({ - bundles: ['test0'], - tabs: ['tab0'], - srcDir: 'src' - }); + expect(lintCall).toMatchObject({ + bundles: ['test0'], + tabs: ['tab0'], + srcDir: 'src' + }); }); it('should exit with code 1 if there are linting errors', async () => { @@ -66,20 +62,17 @@ describe('test eslint command', () => { try { await runCommand(); } catch (error) { - expect(error) - .toEqual(new Error('process.exit called with 1')); + expect(error).toEqual(new Error('process.exit called with 1')); } - expect(lintModule.runEslint) - .toHaveBeenCalledTimes(1); + expect(lintModule.runEslint).toHaveBeenCalledTimes(1); - expect(process.exit) - .toHaveBeenCalledWith(1); + expect(process.exit).toHaveBeenCalledWith(1); }); }); describe('test tsc command', () => { - const runCommand = (...args: string[]) => tscModule.getTscCommand() - .parseAsync(args, { from: 'user' }); + const runCommand = (...args: string[]) => + tscModule.getTscCommand().parseAsync(args, { from: 'user' }); test('regular command function', async () => { mockedTsc.mockResolvedValueOnce({ @@ -92,8 +85,7 @@ describe('test tsc command', () => { await runCommand(); - expect(tscModule.runTsc) - .toHaveBeenCalledTimes(1); + expect(tscModule.runTsc).toHaveBeenCalledTimes(1); }); it('should only typecheck specified bundles and tabs', async () => { @@ -107,16 +99,14 @@ describe('test tsc command', () => { await runCommand('-b', 'test0', '-t', 'tab0'); - expect(tscModule.runTsc) - .toHaveBeenCalledTimes(1); + expect(tscModule.runTsc).toHaveBeenCalledTimes(1); const [tscCall] = mockedTsc.mock.calls[0]; - expect(tscCall) - .toMatchObject({ - bundles: ['test0'], - tabs: ['tab0'], - srcDir: 'src' - }); + expect(tscCall).toMatchObject({ + bundles: ['test0'], + tabs: ['tab0'], + srcDir: 'src' + }); }); it('should exit with code 1 if there are type check errors', async () => { @@ -131,14 +121,11 @@ describe('test tsc command', () => { try { await runCommand(); } catch (error) { - expect(error) - .toEqual(new Error('process.exit called with 1')); + expect(error).toEqual(new Error('process.exit called with 1')); } - expect(tscModule.runTsc) - .toHaveBeenCalledTimes(1); + expect(tscModule.runTsc).toHaveBeenCalledTimes(1); - expect(process.exit) - .toHaveBeenCalledWith(1); + expect(process.exit).toHaveBeenCalledWith(1); }); }); diff --git a/scripts/src/build/prebuild/index.ts b/scripts/src/build/prebuild/index.ts index d8c4832b86..3921bcae93 100644 --- a/scripts/src/build/prebuild/index.ts +++ b/scripts/src/build/prebuild/index.ts @@ -4,9 +4,9 @@ import { eslintResultsLogger, runEslint } from './lint'; import { runTsc, tscResultsLogger } from './tsc'; interface PrebuildResult { - lint?: Awaited> - tsc?: Awaited> - severity: Severity + lint?: Awaited>; + tsc?: Awaited>; + severity: Severity; } export default async function prebuild( diff --git a/scripts/src/build/prebuild/lint.ts b/scripts/src/build/prebuild/lint.ts index 2e4f3669c4..a8fc9e08bd 100644 --- a/scripts/src/build/prebuild/lint.ts +++ b/scripts/src/build/prebuild/lint.ts @@ -12,12 +12,12 @@ import { findSeverity, divideAndRound, type Severity, type AwaitedReturn } from import { createPrebuildCommand, createPrebuildCommandHandler, type PrebuildOptions } from './utils'; interface LintResults { - formatted: string - severity: Severity + formatted: string; + severity: Severity; } interface LintOptions extends Omit { - fix?: boolean + fix?: boolean; } export const runEslint = wrapWithTimer(async ({ bundles, tabs, srcDir, fix }: LintOptions): Promise => { diff --git a/scripts/src/build/prebuild/tsc.ts b/scripts/src/build/prebuild/tsc.ts index 0e7e9d3102..1606e3f810 100644 --- a/scripts/src/build/prebuild/tsc.ts +++ b/scripts/src/build/prebuild/tsc.ts @@ -7,21 +7,21 @@ import { expandBundleNames, expandTabNames, divideAndRound, type AwaitedReturn } import { createPrebuildCommand, createPrebuildCommandHandler, type PrebuildOptions } from './utils'; type TsconfigResult = { - severity: 'error', - results?: ts.Diagnostic[] - error?: any + severity: 'error'; + results?: ts.Diagnostic[]; + error?: any; } | { - severity: 'success', - results: ts.CompilerOptions + severity: 'success'; + results: ts.CompilerOptions; }; type TscResult = { - severity: 'error' - results?: ts.Diagnostic[] - error?: any + severity: 'error'; + results?: ts.Diagnostic[]; + error?: any; } | { - severity: 'success', - results: ts.Diagnostic[] + severity: 'success'; + results: ts.Diagnostic[]; }; async function getTsconfig(srcDir: string): Promise { diff --git a/scripts/src/build/prebuild/utils.ts b/scripts/src/build/prebuild/utils.ts index b0f85e11e3..34084169af 100644 --- a/scripts/src/build/prebuild/utils.ts +++ b/scripts/src/build/prebuild/utils.ts @@ -3,10 +3,10 @@ import { bundlesOption, manifestOption, srcDirOption, tabsOption, type TimedResu import { logInputs, type Severity } from '../utils'; export interface PrebuildOptions { - srcDir: string - manifest: string - bundles: string[] - tabs: string[] + srcDir: string; + manifest: string; + bundles: string[]; + tabs: string[]; } export interface PrebuildResult extends TimedResult {} diff --git a/scripts/src/build/utils.ts b/scripts/src/build/utils.ts index 439b153ea8..79e204e6dd 100644 --- a/scripts/src/build/utils.ts +++ b/scripts/src/build/utils.ts @@ -8,30 +8,30 @@ import { htmlLogger, type buildHtml } from './docs/html'; import prebuild, { formatPrebuildResults } from './prebuild'; export interface BuildOptions { - srcDir: string - outDir: string - manifest: string - lint?: boolean - fix?: boolean - tsc?: boolean - verbose?: boolean + srcDir: string; + outDir: string; + manifest: string; + lint?: boolean; + fix?: boolean; + tsc?: boolean; + verbose?: boolean; } export interface SuccessResult { - name: string - severity: 'success', + name: string; + severity: 'success'; } export interface WarnResult { - name: string, - severity: 'warn', - error: any + name: string; + severity: 'warn'; + error: any; } export interface ErrorResult { - name: string, - severity: 'error', - error: any + name: string; + severity: 'error'; + error: any; } export type OperationResult = ErrorResult | SuccessResult | WarnResult; @@ -194,7 +194,7 @@ export function logInputs( return output.join('\n'); } -type CommandHandler = (opts: BuildOptions & { bundles?: string[] | null, tabs?: string[] | null }) => Promise; +type CommandHandler = (opts: BuildOptions & { bundles?: string[] | null; tabs?: string[] | null }) => Promise; export function createBuildCommandHandler(func: BuildTask, ignore?: 'bundles' | 'tabs'): CommandHandler { return async opts => { diff --git a/scripts/src/commandUtils.ts b/scripts/src/commandUtils.ts index 8ae4498ef8..6022e16663 100644 --- a/scripts/src/commandUtils.ts +++ b/scripts/src/commandUtils.ts @@ -41,8 +41,8 @@ export function promiseAll[]>(...args: T): Promise<{ [K i } export interface TimedResult { - result: T - elapsed: number + result: T; + elapsed: number; } export function wrapWithTimer Promise>(func: T) { diff --git a/scripts/src/manifest.ts b/scripts/src/manifest.ts index 53b38a02c1..52c97c2b07 100644 --- a/scripts/src/manifest.ts +++ b/scripts/src/manifest.ts @@ -1,6 +1,6 @@ import fs from 'fs/promises'; -export type ModuleManifest = Record; +export type ModuleManifest = Record; export async function retrieveManifest(manifest: string) { try { diff --git a/scripts/src/templates/__tests__/names.test.ts b/scripts/src/templates/__tests__/names.test.ts index eaf0b6ce6c..f4a90b8cf0 100644 --- a/scripts/src/templates/__tests__/names.test.ts +++ b/scripts/src/templates/__tests__/names.test.ts @@ -4,8 +4,10 @@ function testFunction( func: (value: string) => boolean, tcs: [string, boolean][] ) { - describe(`Testing ${func.name}`, () => test.each(tcs)('%#: %s', (value, valid) => expect(func(value)) - .toEqual(valid))); + describe(`Testing ${func.name}`, () => + test.each(tcs)('%#: %s', (value, valid) => + expect(func(value)).toEqual(valid) + )); } testFunction(isPascalCase, [ diff --git a/scripts/src/templates/templates/__tab__.tsx b/scripts/src/templates/templates/__tab__.tsx index 34eb95b091..76dd1bcfc5 100644 --- a/scripts/src/templates/templates/__tab__.tsx +++ b/scripts/src/templates/templates/__tab__.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import { IconNames } from '@blueprintjs/icons'; /** * @@ -29,7 +30,7 @@ class Repeat extends React.Component { constructor(props) { super(props); this.state = { - counter: 0, + counter: 0 }; } @@ -67,5 +68,5 @@ export default { * displayed in the side contents panel. * @see https://blueprintjs.com/docs/#icons */ - iconName: 'build', -}; \ No newline at end of file + iconName: IconNames.BUILD +}; diff --git a/scripts/src/testing/__tests__/runner.test.ts b/scripts/src/testing/__tests__/runner.test.ts index e6d93c3cf1..8c5decac2d 100644 --- a/scripts/src/testing/__tests__/runner.test.ts +++ b/scripts/src/testing/__tests__/runner.test.ts @@ -2,8 +2,7 @@ import type { MockedFunction } from 'jest-mock'; import getTestCommand from '..'; import * as runner from '../runner'; -jest.spyOn(runner, 'runJest') - .mockImplementation(jest.fn()); +jest.spyOn(runner, 'runJest').mockImplementation(jest.fn()); const runCommand = (...args: string[]) => getTestCommand() .parseAsync(args, { from: 'user' }); @@ -13,16 +12,13 @@ test('Check that the test command properly passes options to jest', async () => await runCommand('-u', '-w', '--srcDir', 'gg', './src/folder'); const [call] = mockRunJest.mock.calls; - expect(call[0]) - .toEqual(['-u', '-w', './src/folder']); - expect(call[1]) - .toEqual('gg'); + expect(call[0]).toEqual(['-u', '-w', './src/folder']); + expect(call[1]).toEqual('gg'); }); test('Check that the test command handles windows paths as posix paths', async () => { await runCommand('.\\src\\folder'); const [call] = mockRunJest.mock.calls; - expect(call[0]) - .toEqual(['./src/folder']); + expect(call[0]).toEqual(['./src/folder']); }); diff --git a/scripts/src/testing/index.ts b/scripts/src/testing/index.ts index b6c606ee45..e1619bdae0 100644 --- a/scripts/src/testing/index.ts +++ b/scripts/src/testing/index.ts @@ -6,7 +6,7 @@ import { srcDirOption } from '@src/commandUtils'; import { runJest } from './runner'; export type TestCommandOptions = { - srcDir: string + srcDir: string; }; const getTestCommand = () => new Command('test') diff --git a/scripts/tsconfig.json b/scripts/tsconfig.json index 897b90573e..71e5118ef6 100644 --- a/scripts/tsconfig.json +++ b/scripts/tsconfig.json @@ -11,4 +11,4 @@ }, "include": ["./src", "jest.setup.ts"], "exclude": ["./src/templates/templates/**"] -} \ No newline at end of file +} diff --git a/src/bundles/ar/AR.ts b/src/bundles/ar/AR.ts index ba41fdcdc8..7e2f1ec1f8 100644 --- a/src/bundles/ar/AR.ts +++ b/src/bundles/ar/AR.ts @@ -127,7 +127,7 @@ export function createVector3(x: number, y: number, z: number): Vector3 { export function addARObject(arObject: ARObject) { const moduleState = getModuleState(); if (!moduleState) return; - if (moduleState.arObjects.find((item) => item.id === arObject.id)) { + if (moduleState.arObjects.find(item => item.id === arObject.id)) { return; // Already in array } if (arObject.onSelect) { @@ -148,7 +148,7 @@ export function removeARObject(arObject: ARObject) { const moduleState = getModuleState(); if (!moduleState) return; moduleState.arObjects = moduleState.arObjects.filter( - (item) => item.id !== arObject.id, + item => item.id !== arObject.id, ); callARCallback(); } @@ -266,7 +266,7 @@ export function getFrontObject() { const moduleState = getModuleState(); if (!moduleState) return undefined; return moduleState.arObjects.find( - (arObject) => arObject.id === moduleState.selectedObjectId, + arObject => arObject.id === moduleState.selectedObjectId, ); } diff --git a/src/bundles/arcade_2d/audio.ts b/src/bundles/arcade_2d/audio.ts index 28c22a9183..1cf943a44d 100644 --- a/src/bundles/arcade_2d/audio.ts +++ b/src/bundles/arcade_2d/audio.ts @@ -18,10 +18,7 @@ export class AudioClip { private shouldPlay: boolean = false; private shouldLoop: boolean = false; - private constructor( - private url: string, - private volumeLevel: number - ) { + private constructor(private url: string, private volumeLevel: number) { this.id = AudioClip.audioClipCount++; AudioClip.audioClipsIndexMap.set(url, this.id); AudioClip.audioClipsArray.push(this); diff --git a/src/bundles/arcade_2d/phaserScene.ts b/src/bundles/arcade_2d/phaserScene.ts index 5e52cbd242..d2242b2211 100644 --- a/src/bundles/arcade_2d/phaserScene.ts +++ b/src/bundles/arcade_2d/phaserScene.ts @@ -1,9 +1,7 @@ import Phaser from 'phaser'; import { AudioClip } from './audio'; import { DEFAULT_PATH_PREFIX } from './constants'; -import { - config -} from './functions'; +import { config } from './functions'; import { CircleGameObject, GameObject, @@ -68,19 +66,19 @@ export class PhaserScene extends Phaser.Scene { init() { gameState.debugLogArray.length = 0; // Disable context menu within the canvas - this.game.canvas.oncontextmenu = (e) => e.preventDefault(); + this.game.canvas.oncontextmenu = e => e.preventDefault(); } preload() { // Set the default path prefix this.load.setPath(DEFAULT_PATH_PREFIX); - this.sourceGameObjects.forEach((gameObject) => { + this.sourceGameObjects.forEach(gameObject => { if (gameObject instanceof SpriteGameObject) { this.corsAssetsUrl.add(gameObject.getSprite().imageUrl); } }); // Preload sprites (through Cross-Origin resource sharing (CORS)) - this.corsAssetsUrl.forEach((url) => { + this.corsAssetsUrl.forEach(url => { this.load.image(url, url); }); // Preload audio @@ -111,8 +109,13 @@ export class PhaserScene extends Phaser.Scene { if (!config.isDebugEnabled && !this.hasRuntimeError) { gameState.debugLogArray.length = 0; } - this.debugLogText = this.add.text(0, 0, gameState.debugLogArray) - .setWordWrapWidth(config.scale < 1 ? this.renderer.width * config.scale : this.renderer.width) + this.debugLogText = this.add + .text(0, 0, gameState.debugLogArray) + .setWordWrapWidth( + config.scale < 1 + ? this.renderer.width * config.scale + : this.renderer.width + ) .setBackgroundColor('black') .setAlpha(0.8) .setScale(config.scale < 1 ? 1 / config.scale : 1); @@ -126,7 +129,10 @@ export class PhaserScene extends Phaser.Scene { // Set the pointer properties gameState.pointerProps = { ...gameState.pointerProps, - pointerPosition: [Math.trunc(this.input.activePointer.x), Math.trunc(this.input.activePointer.y)], + pointerPosition: [ + Math.trunc(this.input.activePointer.x), + Math.trunc(this.input.activePointer.y) + ], isPointerPrimaryDown: this.input.activePointer.primaryDown, isPointerSecondaryDown: this.input.activePointer.rightButtonDown() }; @@ -158,16 +164,18 @@ export class PhaserScene extends Phaser.Scene { } private createPhaserGameObjects() { - this.sourceGameObjects.forEach((gameObject) => { + this.sourceGameObjects.forEach(gameObject => { const transformProps = gameObject.getTransform(); // Create TextGameObject if (gameObject instanceof TextGameObject) { const text = gameObject.getText().text; - this.phaserGameObjects.push(this.add.text( - transformProps.position[0], - transformProps.position[1], - text - )); + this.phaserGameObjects.push( + this.add.text( + transformProps.position[0], + transformProps.position[1], + text + ) + ); this.phaserGameObjects[gameObject.id].setOrigin(0.5, 0.5); if (gameObject.getHitboxState().isHitboxActive) { this.phaserGameObjects[gameObject.id].setInteractive(); @@ -176,11 +184,13 @@ export class PhaserScene extends Phaser.Scene { // Create SpriteGameObject if (gameObject instanceof SpriteGameObject) { const url = gameObject.getSprite().imageUrl; - this.phaserGameObjects.push(this.add.sprite( - transformProps.position[0], - transformProps.position[1], - url - )); + this.phaserGameObjects.push( + this.add.sprite( + transformProps.position[0], + transformProps.position[1], + url + ) + ); if (gameObject.getHitboxState().isHitboxActive) { this.phaserGameObjects[gameObject.id].setInteractive(); } @@ -189,45 +199,48 @@ export class PhaserScene extends Phaser.Scene { if (gameObject instanceof ShapeGameObject) { if (gameObject instanceof RectangleGameObject) { const shape = gameObject.getShape(); - this.phaserGameObjects.push(this.add.rectangle( - transformProps.position[0], - transformProps.position[1], - shape.width, - shape.height - )); + this.phaserGameObjects.push( + this.add.rectangle( + transformProps.position[0], + transformProps.position[1], + shape.width, + shape.height + ) + ); if (gameObject.getHitboxState().isHitboxActive) { this.phaserGameObjects[gameObject.id].setInteractive(); } } if (gameObject instanceof CircleGameObject) { const shape = gameObject.getShape(); - this.phaserGameObjects.push(this.add.circle( - transformProps.position[0], - transformProps.position[1], - shape.radius - )); + this.phaserGameObjects.push( + this.add.circle( + transformProps.position[0], + transformProps.position[1], + shape.radius + ) + ); if (gameObject.getHitboxState().isHitboxActive) { this.phaserGameObjects[gameObject.id].setInteractive( - new Phaser.Geom.Circle( - shape.radius, - shape.radius, - shape.radius - ), Phaser.Geom.Circle.Contains + new Phaser.Geom.Circle(shape.radius, shape.radius, shape.radius), + Phaser.Geom.Circle.Contains ); } } if (gameObject instanceof TriangleGameObject) { const shape = gameObject.getShape(); - this.phaserGameObjects.push(this.add.triangle( - transformProps.position[0], - transformProps.position[1], - shape.x1, - shape.y1, - shape.x2, - shape.y2, - shape.x3, - shape.y3 - )); + this.phaserGameObjects.push( + this.add.triangle( + transformProps.position[0], + transformProps.position[1], + shape.x1, + shape.y1, + shape.x2, + shape.y2, + shape.x3, + shape.y3 + ) + ); if (gameObject.getHitboxState().isHitboxActive) { this.phaserGameObjects[gameObject.id].setInteractive( new Phaser.Geom.Triangle( @@ -237,7 +250,8 @@ export class PhaserScene extends Phaser.Scene { shape.y2, shape.x3, shape.y3 - ), Phaser.Geom.Triangle.Contains + ), + Phaser.Geom.Triangle.Contains ); } } @@ -265,10 +279,12 @@ export class PhaserScene extends Phaser.Scene { private createAudioClips() { try { this.sourceAudioClips.forEach((audioClip: AudioClip) => { - this.phaserAudioClips.push(this.sound.add(audioClip.getUrl(), { - loop: audioClip.shouldAudioClipLoop(), - volume: audioClip.getVolumeLevel() - })); + this.phaserAudioClips.push( + this.sound.add(audioClip.getUrl(), { + loop: audioClip.shouldAudioClipLoop(), + volume: audioClip.getVolumeLevel() + }) + ); }); } catch (error) { this.hasRuntimeError = true; diff --git a/src/bundles/binary_tree/functions.ts b/src/bundles/binary_tree/functions.ts index b2d53b977e..5d09af855f 100644 --- a/src/bundles/binary_tree/functions.ts +++ b/src/bundles/binary_tree/functions.ts @@ -69,9 +69,7 @@ export function is_tree( * @param v Value to be tested * @returns bool */ -export function is_empty_tree( - value: any -): boolean { +export function is_empty_tree(value: any): boolean { return value === null; } @@ -85,9 +83,7 @@ export function is_empty_tree( * @param t BinaryTree to be accessed * @returns Value */ -export function entry( - t: BinaryTree -): boolean { +export function entry(t: BinaryTree): boolean { if (Array.isArray(t) && t.length === 2) { return t[0]; } @@ -106,9 +102,7 @@ export function entry( * @param t BinaryTree to be accessed * @returns BinaryTree */ -export function left_branch( - t: BinaryTree -): BinaryTree { +export function left_branch(t: BinaryTree): BinaryTree { if (Array.isArray(t) && t.length === 2 && Array.isArray(t[1]) && t[1].length === 2) { return t[1][0]; @@ -128,9 +122,7 @@ export function left_branch( * @param t BinaryTree to be accessed * @returns BinaryTree */ -export function right_branch( - t: BinaryTree -): BinaryTree { +export function right_branch(t: BinaryTree): BinaryTree { if (Array.isArray(t) && t.length === 2 && Array.isArray(t[1]) && t[1].length === 2 && Array.isArray(t[1][1]) && t[1][1].length === 2) { diff --git a/src/bundles/communication/GlobalStateController.ts b/src/bundles/communication/GlobalStateController.ts index 03c86b1fb9..d51cf7b297 100644 --- a/src/bundles/communication/GlobalStateController.ts +++ b/src/bundles/communication/GlobalStateController.ts @@ -63,8 +63,8 @@ export class GlobalStateController { try { let newGlobalState = { ...this.globalState }; if ( - this.globalState instanceof Array || - typeof this.globalState === 'string' + this.globalState instanceof Array + || typeof this.globalState === 'string' ) { newGlobalState = {}; } @@ -72,9 +72,9 @@ export class GlobalStateController { for (let i = 1; i < splitTopic.length - 1; i++) { const subTopic = splitTopic[i]; if ( - !(currentJson[subTopic] instanceof Object) || - currentJson[subTopic] instanceof Array || - typeof currentJson[subTopic] === 'string' + !(currentJson[subTopic] instanceof Object) + || currentJson[subTopic] instanceof Array + || typeof currentJson[subTopic] === 'string' ) { currentJson[subTopic] = {}; } diff --git a/src/bundles/communication/MultiUserController.ts b/src/bundles/communication/MultiUserController.ts index 1d29f06a10..f2520f539f 100644 --- a/src/bundles/communication/MultiUserController.ts +++ b/src/bundles/communication/MultiUserController.ts @@ -7,8 +7,7 @@ import { MqttController, STATE_DISCONNECTED } from './MqttController'; export class MultiUserController { controller: MqttController | null = null; connectionState: string = STATE_DISCONNECTED; - messageCallbacks: Map void> = - new Map(); + messageCallbacks: Map void> = new Map(); /** * Sets up and connect to the MQTT link. diff --git a/src/bundles/communication/__tests__/index.ts b/src/bundles/communication/__tests__/index.ts index ff8b8cdb7b..5edbff76ee 100644 --- a/src/bundles/communication/__tests__/index.ts +++ b/src/bundles/communication/__tests__/index.ts @@ -6,7 +6,7 @@ multiUser.setupController('broker.hivemq.com', 8884, '', ''); const globalStateController = new GlobalStateController( 'test', multiUser, - (_) => {}, + _ => {} ); // Empty Root - Replace root. @@ -15,18 +15,18 @@ test('Empty Root Set Null', () => { globalStateController.globalState = undefined; globalStateController.parseGlobalStateMessage('', JSON.stringify(null)); expect(JSON.stringify(globalStateController.globalState)).toBe( - JSON.stringify(null), + JSON.stringify(null) ); }); test('Empty Root Set Object', () => { globalStateController.globalState = undefined; const object = { - a: 'b', + a: 'b' }; globalStateController.parseGlobalStateMessage('', JSON.stringify(object)); expect(JSON.stringify(globalStateController.globalState)).toBe( - JSON.stringify(object), + JSON.stringify(object) ); }); @@ -34,36 +34,36 @@ test('Empty Root Set Object', () => { test('Non-Empty Root Set Empty', () => { const object = { - a: 'b', + a: 'b' }; globalStateController.globalState = object; globalStateController.parseGlobalStateMessage('', JSON.stringify(undefined)); expect(JSON.stringify(globalStateController.globalState)).toBe( - JSON.stringify(undefined), + JSON.stringify(undefined) ); }); test('Non-Empty Root Set Null', () => { const object = { - a: 'b', + a: 'b' }; globalStateController.globalState = object; globalStateController.parseGlobalStateMessage('', JSON.stringify(null)); expect(JSON.stringify(globalStateController.globalState)).toBe( - JSON.stringify(null), + JSON.stringify(null) ); }); test('Non-Empty Root Set Object', () => { globalStateController.globalState = { - a: 'b', + a: 'b' }; const object = { - c: 'd', + c: 'd' }; globalStateController.parseGlobalStateMessage('', JSON.stringify(object)); expect(JSON.stringify(globalStateController.globalState)).toBe( - JSON.stringify(object), + JSON.stringify(object) ); }); @@ -72,78 +72,78 @@ test('Non-Empty Root Set Object', () => { test('Branch Value Set Empty', () => { globalStateController.globalState = { a: 'b', - c: 'd', + c: 'd' }; globalStateController.parseGlobalStateMessage('a', JSON.stringify(undefined)); expect(JSON.stringify(globalStateController.globalState)).toBe( - JSON.stringify({ c: 'd' }), + JSON.stringify({ c: 'd' }) ); }); test('Nested Branch Value Set Empty', () => { globalStateController.globalState = { a: { - b: 'c', - }, + b: 'c' + } }; globalStateController.parseGlobalStateMessage( 'a/b', - JSON.stringify(undefined), + JSON.stringify(undefined) ); expect(JSON.stringify(globalStateController.globalState)).toBe( - JSON.stringify({ a: {} }), + JSON.stringify({ a: {} }) ); }); test('Branch Value Set Null', () => { globalStateController.globalState = { a: 'b', - c: 'd', + c: 'd' }; globalStateController.parseGlobalStateMessage('a', JSON.stringify(null)); expect(JSON.stringify(globalStateController.globalState)).toBe( - JSON.stringify({ a: null, c: 'd' }), + JSON.stringify({ a: null, c: 'd' }) ); }); test('Nested Branch Value Set Null', () => { globalStateController.globalState = { a: { - b: 'c', - }, + b: 'c' + } }; globalStateController.parseGlobalStateMessage('a/b', JSON.stringify(null)); expect(JSON.stringify(globalStateController.globalState)).toBe( - JSON.stringify({ a: { b: null } }), + JSON.stringify({ a: { b: null } }) ); }); test('Branch Value Set Object', () => { globalStateController.globalState = { a: 'b', - c: 'd', + c: 'd' }; const object = { - b: 'e', + b: 'e' }; globalStateController.parseGlobalStateMessage('a', JSON.stringify(object)); expect(JSON.stringify(globalStateController.globalState)).toBe( - JSON.stringify({ a: object, c: 'd' }), + JSON.stringify({ a: object, c: 'd' }) ); }); test('Nested Branch Value Set Object', () => { globalStateController.globalState = { a: { - b: 'c', - }, + b: 'c' + } }; const object = { - c: 'd', + c: 'd' }; globalStateController.parseGlobalStateMessage('a/b', JSON.stringify(object)); expect(JSON.stringify(globalStateController.globalState)).toBe( - JSON.stringify({ a: { b: object } }), + JSON.stringify({ a: { b: object } }) ); }); @@ -152,73 +152,73 @@ test('Nested Branch Value Set Object', () => { test('Branch Object Set Empty', () => { globalStateController.globalState = { a: { b: 'c' }, - d: 'e', + d: 'e' }; globalStateController.parseGlobalStateMessage('a', JSON.stringify(undefined)); expect(JSON.stringify(globalStateController.globalState)).toBe( - JSON.stringify({ d: 'e' }), + JSON.stringify({ d: 'e' }) ); }); test('Nested Branch Object Set Empty', () => { globalStateController.globalState = { - a: { b: { c: 'd' }, e: 'f' }, + a: { b: { c: 'd' }, e: 'f' } }; globalStateController.parseGlobalStateMessage( 'a/b', - JSON.stringify(undefined), + JSON.stringify(undefined) ); expect(JSON.stringify(globalStateController.globalState)).toBe( - JSON.stringify({ a: { e: 'f' } }), + JSON.stringify({ a: { e: 'f' } }) ); }); test('Branch Object Set Null', () => { globalStateController.globalState = { a: { b: 'c' }, - d: 'e', + d: 'e' }; globalStateController.parseGlobalStateMessage('a', JSON.stringify(null)); expect(JSON.stringify(globalStateController.globalState)).toBe( - JSON.stringify({ a: null, d: 'e' }), + JSON.stringify({ a: null, d: 'e' }) ); }); test('Nested Branch Object Set Null', () => { globalStateController.globalState = { - a: { b: { c: 'd' }, e: 'f' }, + a: { b: { c: 'd' }, e: 'f' } }; globalStateController.parseGlobalStateMessage('a/b', JSON.stringify(null)); expect(JSON.stringify(globalStateController.globalState)).toBe( - JSON.stringify({ a: { b: null, e: 'f' } }), + JSON.stringify({ a: { b: null, e: 'f' } }) ); }); test('Branch Object Set Object', () => { globalStateController.globalState = { a: { b: 'c', d: 'e' }, - f: 'g', + f: 'g' }; const object = { d: 'f', - g: 'h', + g: 'h' }; globalStateController.parseGlobalStateMessage('a', JSON.stringify(object)); expect(JSON.stringify(globalStateController.globalState)).toBe( - JSON.stringify({ a: object, f: 'g' }), + JSON.stringify({ a: object, f: 'g' }) ); }); test('Nested Branch Object Set Null 2', () => { globalStateController.globalState = { - a: { b: { c: 'd' }, e: 'f' }, + a: { b: { c: 'd' }, e: 'f' } }; const object = { c: 'g', - h: 'i', + h: 'i' }; globalStateController.parseGlobalStateMessage('a/b', JSON.stringify(object)); expect(JSON.stringify(globalStateController.globalState)).toBe( - JSON.stringify({ a: { b: object, e: 'f' } }), + JSON.stringify({ a: { b: object, e: 'f' } }) ); }); diff --git a/src/bundles/csg/functions.ts b/src/bundles/csg/functions.ts index f46034e09b..3c96f41441 100644 --- a/src/bundles/csg/functions.ts +++ b/src/bundles/csg/functions.ts @@ -716,8 +716,7 @@ export function render(operable: Operable): RenderGroup { // Trigger a new render group for use with subsequent renders. // Render group is returned for REPL text only; do not document - return Core.getRenderGroupManager() - .nextRenderGroup(); + return Core.getRenderGroupManager().nextRenderGroup(); } /** @@ -734,8 +733,7 @@ export function render_grid(operable: Operable): RenderGroup { operable.store(); - return Core.getRenderGroupManager() - .nextRenderGroup(true); + return Core.getRenderGroupManager().nextRenderGroup(true); } /** @@ -752,8 +750,7 @@ export function render_axes(operable: Operable): RenderGroup { operable.store(); - return Core.getRenderGroupManager() - .nextRenderGroup(undefined, true); + return Core.getRenderGroupManager().nextRenderGroup(undefined, true); } /** @@ -770,6 +767,5 @@ export function render_grid_axes(operable: Operable): RenderGroup { operable.store(); - return Core.getRenderGroupManager() - .nextRenderGroup(true, true); + return Core.getRenderGroupManager().nextRenderGroup(true, true); } diff --git a/src/bundles/csg/jscad/renderer.ts b/src/bundles/csg/jscad/renderer.ts index d82a6505f8..2df90d28d3 100644 --- a/src/bundles/csg/jscad/renderer.ts +++ b/src/bundles/csg/jscad/renderer.ts @@ -45,10 +45,7 @@ function solidsToGeometryEntities(solids: Solid[]): GeometryEntity[] { const options: EntitiesFromSolidsOptions = { color: hexToAlphaColor(DEFAULT_COLOR) }; - return (entitiesFromSolids( - options, - ...solids - ) as unknown) as GeometryEntity[]; + return entitiesFromSolids(options, ...solids) as unknown as GeometryEntity[]; } function neatGridDistance(rawDistance: number) { @@ -186,10 +183,10 @@ export function updateStates( cameraState: PerspectiveCameraState, controlsState: ControlsState ) { - const states: UpdatedStates = (orbit.update({ + const states: UpdatedStates = orbit.update({ camera: cameraState, controls: controlsState - }) as unknown) as UpdatedStates; + }) as unknown as UpdatedStates; cameraState.position = states.camera.position; cameraState.view = states.camera.view; @@ -204,11 +201,11 @@ export function zoomToFit( controlsState: ControlsState, geometryEntities: GeometryEntity[] ) { - const states: ZoomToFitStates = (orbit.zoomToFit({ + const states: ZoomToFitStates = orbit.zoomToFit({ camera: cameraState, controls: controlsState, entities: geometryEntities as any - }) as unknown) as ZoomToFitStates; + }) as unknown as ZoomToFitStates; cameraState.target = states.camera.target; @@ -221,14 +218,14 @@ export function rotate( rotateX: number, rotateY: number ) { - const states: RotateStates = (orbit.rotate( + const states: RotateStates = orbit.rotate( { camera: cameraState, controls: controlsState, speed: ROTATION_SPEED }, [rotateX, rotateY] - ) as unknown) as RotateStates; + ) as unknown as RotateStates; controlsState.thetaDelta = states.controls.thetaDelta; controlsState.phiDelta = states.controls.phiDelta; @@ -240,13 +237,13 @@ export function pan( panX: number, panY: number ) { - const states: PanStates = (orbit.pan( + const states: PanStates = orbit.pan( { camera: cameraState, controls: controlsState }, [panX * X_FACTOR, panY * Y_FACTOR] - ) as unknown) as PanStates; + ) as unknown as PanStates; cameraState.position = states.camera.position; cameraState.target = states.camera.target; diff --git a/src/bundles/csg/jscad/types.ts b/src/bundles/csg/jscad/types.ts index db0e9f13df..4051990ed9 100644 --- a/src/bundles/csg/jscad/types.ts +++ b/src/bundles/csg/jscad/types.ts @@ -158,7 +158,7 @@ export type DrawCommandMakers = Record; export type Mat4 = Float32Array; export type PerspectiveCameraState = Omit< typeof cameras.perspective.cameraState, -'position' | 'target' | 'view' + 'position' | 'target' | 'view' > & { target: Coordinates; @@ -209,7 +209,7 @@ export type WrappedRenderer = (data: WrappedRendererData) => void; */ export type ControlsState = Omit< typeof orbit.controlsState, -'phiDelta' | 'scale' | 'thetaDelta' + 'phiDelta' | 'scale' | 'thetaDelta' > & typeof orbit.controlsProps & { scale: number; diff --git a/src/bundles/csg/types.ts b/src/bundles/csg/types.ts index 0668fbaa1c..7901655bc8 100644 --- a/src/bundles/csg/types.ts +++ b/src/bundles/csg/types.ts @@ -34,7 +34,7 @@ export type OrthographicCamera = typeof orthographicCamera; export type PerspectiveCameraState = Omit< typeof perspectiveCamera.cameraState, -'position' | 'target' | 'view' + 'position' | 'target' | 'view' > & { target: CoordinatesXYZ; @@ -47,7 +47,7 @@ export type CameraState = OrthographicCameraState | PerspectiveCameraState; // @jscad\regl-renderer\src\controls\orbitControls.js export type Controls = Omit< typeof controls, -'pan' | 'rotate' | 'update' | 'zoomToFit' + 'pan' | 'rotate' | 'update' | 'zoomToFit' > & { update: ControlsUpdate.Function; zoomToFit: ControlsZoomToFit.Function; @@ -125,7 +125,7 @@ export type ControlsPan = ( export type ControlsState = Omit< typeof controls.controlsState, -'phiDelta' | 'scale' | 'thetaDelta' + 'phiDelta' | 'scale' | 'thetaDelta' > & typeof controls.controlsProps & { scale: number; diff --git a/src/bundles/csg/utilities.ts b/src/bundles/csg/utilities.ts index af4e6e699f..5d3bc03a0a 100644 --- a/src/bundles/csg/utilities.ts +++ b/src/bundles/csg/utilities.ts @@ -108,10 +108,9 @@ export class Shape implements Operable, ReplResult { } store(newTransforms: Mat4 = mat4.create()): void { - Core.getRenderGroupManager() - .storeShape( - this.applyTransforms(newTransforms) as Shape - ); + Core.getRenderGroupManager().storeShape( + this.applyTransforms(newTransforms) as Shape + ); } translate(offsets: [number, number, number]): Shape { diff --git a/src/bundles/curve/__tests__/curve.ts b/src/bundles/curve/__tests__/curve.ts index 4fc993db14..51a8933c27 100644 --- a/src/bundles/curve/__tests__/curve.ts +++ b/src/bundles/curve/__tests__/curve.ts @@ -6,16 +6,25 @@ function evalCurve(curve: Curve, numPoints: number) { } test('Ensure that invalid curves error gracefully', () => { - expect(() => evalCurve((t) => 1 as any, 200)) - .toThrowErrorMatchingInlineSnapshot('"Expected curve to return a point, got \'1\' at t=0"'); + expect(() => + evalCurve(t => 1 as any, 200) + ).toThrowErrorMatchingInlineSnapshot( + '"Expected curve to return a point, got \'1\' at t=0"' + ); }); test('Using 3D render functions with animate_curve should throw errors', () => { - expect(() => animate_curve(1, 60, draw_3D_connected(200), (t0) => (t1) => make_point(t0, t1))) - .toThrowErrorMatchingInlineSnapshot('"animate_curve cannot be used with 3D draw function!"'); + expect(() => + animate_curve(1, 60, draw_3D_connected(200), t0 => t1 => make_point(t0, t1)) + ).toThrowErrorMatchingInlineSnapshot( + '"animate_curve cannot be used with 3D draw function!"' + ); }); test('Using 2D render functions with animate_3D_curve should throw errors', () => { - expect(() => animate_3D_curve(1, 60, draw_connected(200), (t0) => (t1) => make_point(t0, t1))) - .toThrowErrorMatchingInlineSnapshot('"animate_3D_curve cannot be used with 2D draw function!"'); + expect(() => + animate_3D_curve(1, 60, draw_connected(200), t0 => t1 => make_point(t0, t1)) + ).toThrowErrorMatchingInlineSnapshot( + '"animate_3D_curve cannot be used with 2D draw function!"' + ); }); diff --git a/src/bundles/curve/functions.ts b/src/bundles/curve/functions.ts index 701d1c296f..b665169abd 100644 --- a/src/bundles/curve/functions.ts +++ b/src/bundles/curve/functions.ts @@ -612,7 +612,7 @@ export function rotate_around_origin( * @returns function that takes a Curve and returns a Curve */ export function scale(a: number, b: number, c: number): CurveTransformer { - return (curve) => { + return curve => { const transformation = (cf: Curve) => (t: number) => { const ct = cf(t); const a1 = a === undefined ? 1 : a; @@ -684,7 +684,7 @@ export function put_in_standard_position(curve: Curve): Curve { * @returns result Curve */ export function connect_rigidly(curve1: Curve, curve2: Curve): Curve { - return (t) => (t < 1 / 2 ? curve1(2 * t) : curve2(2 * t - 1)); + return t => (t < 1 / 2 ? curve1(2 * t) : curve2(2 * t - 1)); } /** diff --git a/src/bundles/curve/types.ts b/src/bundles/curve/types.ts index 9176542d82..facd6104f6 100644 --- a/src/bundles/curve/types.ts +++ b/src/bundles/curve/types.ts @@ -3,7 +3,7 @@ import type { ReplResult } from '../../typings/type_helpers'; import type { Curve, CurveDrawn } from './curves_webgl'; export type CurveModuleState = { - drawnCurves: (AnimatedCurve | CurveDrawn)[] + drawnCurves: (AnimatedCurve | CurveDrawn)[]; }; /** A function that takes in CurveFunction and returns a tranformed CurveFunction. */ @@ -23,7 +23,7 @@ export type CurveAnimation = (t: number) => Curve; * a CurveFunction and returns a ShapeDrawn based on its specifications. */ export type RenderFunction = ((func: Curve) => CurveDrawn) & { - is3D: boolean + is3D: boolean; }; export class AnimatedCurve extends glAnimation implements ReplResult { diff --git a/src/bundles/game/functions.ts b/src/bundles/game/functions.ts index 9df32eafde..933a2c2c9f 100644 --- a/src/bundles/game/functions.ts +++ b/src/bundles/game/functions.ts @@ -619,10 +619,7 @@ export function create_image( y: number, asset_key: string ): GameObject | undefined { - if ( - preloadImageMap.get(asset_key) - || preloadSpritesheetMap.get(asset_key) - ) { + if (preloadImageMap.get(asset_key) || preloadSpritesheetMap.get(asset_key)) { const image = new Phaser.GameObjects.Sprite(scene(), x, y, asset_key); return set_type(image, ObjectTypes.ImageType); } @@ -783,8 +780,7 @@ export function add_to_container( is_type(container, ObjectTypes.ContainerType) && is_any_type(obj, ObjTypes) ) { - get_container(container) - .add(get_game_obj(obj)); + get_container(container).add(get_game_obj(obj)); return container; } throw_error( @@ -803,8 +799,7 @@ export function add_to_container( */ export function destroy_obj(obj: GameObject) { if (is_any_type(obj, ObjTypes)) { - get_game_obj(obj) - .destroy(); + get_game_obj(obj).destroy(); } else { throw_error(`${obj} is not of type ${ObjTypes}`); } @@ -825,8 +820,7 @@ export function set_display_size( y: number ): GameObject | undefined { if (is_any_type(obj, ObjTypes)) { - get_game_obj(obj) - .setDisplaySize(x, y); + get_game_obj(obj).setDisplaySize(x, y); return obj; } throw_error(`${obj} is not of type ${ObjTypes}`); @@ -842,8 +836,7 @@ export function set_display_size( */ export function set_alpha(obj: GameObject, alpha: number): GameObject | undefined { if (is_any_type(obj, ObjTypes)) { - get_game_obj(obj) - .setAlpha(alpha); + get_game_obj(obj).setAlpha(alpha); return obj; } throw_error(`${obj} is not of type ${ObjTypes}`); @@ -865,8 +858,7 @@ export function set_interactive( config: ObjectConfig = {} ): GameObject | undefined { if (is_any_type(obj, ObjTypes)) { - get_game_obj(obj) - .setInteractive(config); + get_game_obj(obj).setInteractive(config); return obj; } throw_error(`${obj} is not of type ${ObjTypes}`); @@ -909,8 +901,7 @@ export function set_position( y: number ): GameObject | undefined { if (obj && is_any_type(obj, ObjTypes)) { - get_game_obj(obj) - .setPosition(x, y); + get_game_obj(obj).setPosition(x, y); return obj; } throw_error(`${obj} is not of type ${ObjTypes}`); @@ -931,8 +922,7 @@ export function set_scale( y: number ): GameObject | undefined { if (is_any_type(obj, ObjTypes)) { - get_game_obj(obj) - .setScale(x, y); + get_game_obj(obj).setScale(x, y); return obj; } throw_error(`${obj} is not of type ${ObjTypes}`); @@ -948,8 +938,7 @@ export function set_scale( */ export function set_rotation(obj: GameObject, rad: number): GameObject | undefined { if (is_any_type(obj, ObjTypes)) { - get_game_obj(obj) - .setRotation(rad); + get_game_obj(obj).setRotation(rad); return obj; } throw_error(`${obj} is not of type ${ObjTypes}`); @@ -1020,8 +1009,7 @@ export function add_listener( callback: Function ): GameObject | undefined { if (is_any_type(obj, ObjTypes)) { - const listener = get_game_obj(obj) - .addListener(event, callback); + const listener = get_game_obj(obj).addListener(event, callback); return set_type(listener, ListenerTypes.InputPlugin); } throw_error(`${obj} is not of type ${ObjTypes}`); @@ -1061,8 +1049,7 @@ export function add_keyboard_listener( */ export function remove_listener(listener: GameObject): boolean { if (is_any_type(listener, ListnerTypes)) { - get_input_obj(listener) - .removeAllListeners(); + get_input_obj(listener).removeAllListeners(); return true; } return false; @@ -1114,7 +1101,7 @@ const gameFunctions = [ // Inject minArgsNeeded to allow module varargs // Remove if module varargs is fixed on js-slang side -gameFunctions.forEach((fn) => { +gameFunctions.forEach(fn => { const dummy = fn as any; dummy.minArgsNeeded = fn.length; }); diff --git a/src/bundles/game/types.ts b/src/bundles/game/types.ts index 4ff97dcdcf..f912e7658d 100644 --- a/src/bundles/game/types.ts +++ b/src/bundles/game/types.ts @@ -7,7 +7,8 @@ export type RawGameElement = | Phaser.GameObjects.Text; export type RawGameShape = - Phaser.GameObjects.Ellipse | Phaser.GameObjects.Rectangle; + | Phaser.GameObjects.Ellipse + | Phaser.GameObjects.Rectangle; export type RawGameObject = RawGameElement | RawGameShape; diff --git a/src/bundles/painter/functions.ts b/src/bundles/painter/functions.ts index e045328cbb..da8059a19f 100644 --- a/src/bundles/painter/functions.ts +++ b/src/bundles/painter/functions.ts @@ -50,16 +50,20 @@ export function display_painter(painter: (frame: Frame) => void) { y: y_s }; drawnPainters.push( - new LinePlot(draw_new_painter, { - ...data, - mode: 'lines' - } as Data, { - xaxis: { visible: true }, - yaxis: { - visible: true, - scaleanchor: 'x' + new LinePlot( + draw_new_painter, + { + ...data, + mode: 'lines' + } as Data, + { + xaxis: { visible: true }, + yaxis: { + visible: true, + scaleanchor: 'x' + } } - }) + ) ); }; } diff --git a/src/bundles/physics_2d/PhysicsObject.ts b/src/bundles/physics_2d/PhysicsObject.ts index e5cbee63e7..78379fa533 100644 --- a/src/bundles/physics_2d/PhysicsObject.ts +++ b/src/bundles/physics_2d/PhysicsObject.ts @@ -124,7 +124,7 @@ export class PhysicsObject implements ReplResult { (forceWithPos: ForceWithPos) => forceWithPos.force.start_time + forceWithPos.force.duration > world_time ); - this.forcesAtAPoint.forEach((forceWithPos) => { + this.forcesAtAPoint.forEach(forceWithPos => { const force = forceWithPos.force; this.body.ApplyForce( force.direction.Scale(force.magnitude), @@ -150,8 +150,7 @@ export class PhysicsObject implements ReplResult { } public toReplString = () => ` - Mass: ${this.getMass() - .toFixed(ACCURACY)} + Mass: ${this.getMass().toFixed(ACCURACY)} Position: [${this.getPosition().x.toFixed( ACCURACY )},${this.getPosition().y.toFixed(ACCURACY)}] @@ -159,10 +158,8 @@ export class PhysicsObject implements ReplResult { ACCURACY )},${this.getVelocity().y.toFixed(ACCURACY)}] - Rotation: ${this.getRotation() - .toFixed(ACCURACY)} - AngularVelocity: [${this.getAngularVelocity() - .toFixed(ACCURACY)}]`; + Rotation: ${this.getRotation().toFixed(ACCURACY)} + AngularVelocity: [${this.getAngularVelocity().toFixed(ACCURACY)}]`; public scale_size(scale: number) { if (this.shape instanceof b2CircleShape) { @@ -170,7 +167,7 @@ export class PhysicsObject implements ReplResult { } else if (this.shape instanceof b2PolygonShape) { const centroid: b2Vec2 = this.shape.m_centroid; const arr: b2Vec2[] = []; - this.shape.m_vertices.forEach((vec) => { + this.shape.m_vertices.forEach(vec => { arr.push( new b2Vec2( centroid.x + scale * (vec.x - centroid.x), @@ -178,8 +175,7 @@ export class PhysicsObject implements ReplResult { ) ); }); - this.shape = new b2PolygonShape() - .Set(arr); + this.shape = new b2PolygonShape().Set(arr); } const f: b2Fixture = this.fixture; this.body.DestroyFixture(this.fixture); diff --git a/src/bundles/physics_2d/PhysicsWorld.ts b/src/bundles/physics_2d/PhysicsWorld.ts index 04132ca479..da87c17e95 100644 --- a/src/bundles/physics_2d/PhysicsWorld.ts +++ b/src/bundles/physics_2d/PhysicsWorld.ts @@ -111,7 +111,7 @@ export class PhysicsWorld { Objects: `; - this.physicsObjects.forEach((obj) => { + this.physicsObjects.forEach(obj => { world_status += ` ------------------------ ${obj.toReplString()} diff --git a/src/bundles/physics_2d/functions.ts b/src/bundles/physics_2d/functions.ts index 83beb643f8..9ebf42e560 100644 --- a/src/bundles/physics_2d/functions.ts +++ b/src/bundles/physics_2d/functions.ts @@ -120,8 +120,7 @@ export function add_wall(pos: Vector2, rot: number, size: Vector2) { new PhysicsObject( pos, rot, - new b2PolygonShape() - .SetAsBox(size.x / 2, size.y / 2), + new b2PolygonShape().SetAsBox(size.x / 2, size.y / 2), true, world ) @@ -152,8 +151,7 @@ export function add_box_object( const newObj: PhysicsObject = new PhysicsObject( pos, rot, - new b2PolygonShape() - .SetAsBox(size.x / 2, size.y / 2), + new b2PolygonShape().SetAsBox(size.x / 2, size.y / 2), isStatic, world ); @@ -185,8 +183,7 @@ export function add_circle_object( const newObj: PhysicsObject = new PhysicsObject( pos, rot, - new b2CircleShape() - .Set(new Vector2(), radius), + new b2CircleShape().Set(new Vector2(), radius), isStatic, world ); @@ -220,12 +217,11 @@ export function add_triangle_object( const newObj: PhysicsObject = new PhysicsObject( pos, rot, - new b2PolygonShape() - .Set([ - new Vector2(-base / 2, -height / 2), - new Vector2(base / 2, -height / 2), - new Vector2(0, height / 2) - ]), + new b2PolygonShape().Set([ + new Vector2(-base / 2, -height / 2), + new Vector2(base / 2, -height / 2), + new Vector2(0, height / 2) + ]), isStatic, world ); diff --git a/src/bundles/physics_2d/index.ts b/src/bundles/physics_2d/index.ts index e6efaaa6e8..836afd7ed8 100644 --- a/src/bundles/physics_2d/index.ts +++ b/src/bundles/physics_2d/index.ts @@ -48,7 +48,7 @@ * The suggested time step is 1/60 (seconds). * * Visualization of the physics world can also be seen in the display tab. -* + * * The following example simulates a free fall of a circle object. * * ``` diff --git a/src/bundles/pix_n_flix/functions.ts b/src/bundles/pix_n_flix/functions.ts index 353cea7e28..7943b9b869 100644 --- a/src/bundles/pix_n_flix/functions.ts +++ b/src/bundles/pix_n_flix/functions.ts @@ -206,7 +206,7 @@ function playVideoElement() { .then(() => { videoIsPlaying = true; }) - .catch((err) => { + .catch(err => { console.warn(err); }); } @@ -263,7 +263,7 @@ function loadMedia(): void { navigator.mediaDevices .getUserMedia({ video: true }) - .then((stream) => { + .then(stream => { videoElement.srcObject = stream; videoElement.onloadedmetadata = () => setAspectRatioDimensions( videoElement.videoWidth, @@ -271,7 +271,7 @@ function loadMedia(): void { ); toRunLateQueue = true; }) - .catch((error) => { + .catch(error => { const errorMessage = `${error.name}: ${error.message}`; console.error(errorMessage); errorLogger(errorMessage, false); @@ -467,10 +467,9 @@ function deinit(): void { if (!stream) { return; } - stream.getTracks() - .forEach((track) => { - track.stop(); - }); + stream.getTracks().forEach(track => { + track.stop(); + }); } // ============================================================================= diff --git a/src/bundles/plotly/sound_functions.ts b/src/bundles/plotly/sound_functions.ts index 42ad074af3..9f95d6c4f8 100644 --- a/src/bundles/plotly/sound_functions.ts +++ b/src/bundles/plotly/sound_functions.ts @@ -7,8 +7,8 @@ import { type Sound, type Wave } from '../sound/types'; export function is_sound(x: any): x is Sound { return ( is_pair(x) - && typeof get_wave(x) === 'function' - && typeof get_duration(x) === 'number' + && typeof get_wave(x) === 'function' + && typeof get_duration(x) === 'number' ); } /** diff --git a/src/bundles/repeat/__tests__/index.ts b/src/bundles/repeat/__tests__/index.ts index e4e5537636..603df598b8 100644 --- a/src/bundles/repeat/__tests__/index.ts +++ b/src/bundles/repeat/__tests__/index.ts @@ -2,16 +2,13 @@ import { repeat, twice, thrice } from '../functions'; // Test functions test('repeat works correctly and repeats function n times', () => { - expect(repeat((x: number) => x + 1, 5)(1)) - .toBe(6); + expect(repeat((x: number) => x + 1, 5)(1)).toBe(6); }); test('twice works correctly and repeats function twice', () => { - expect(twice((x: number) => x + 1)(1)) - .toBe(3); + expect(twice((x: number) => x + 1)(1)).toBe(3); }); test('thrice works correctly and repeats function thrice', () => { - expect(thrice((x: number) => x + 1)(1)) - .toBe(4); + expect(thrice((x: number) => x + 1)(1)).toBe(4); }); diff --git a/src/bundles/repl/functions.ts b/src/bundles/repl/functions.ts index 948e3c8d14..15834e693a 100644 --- a/src/bundles/repl/functions.ts +++ b/src/bundles/repl/functions.ts @@ -25,7 +25,7 @@ context.moduleContexts.repl.state = INSTANCE; */ export function set_evaluator(evalFunc: Function) { if (!(evalFunc instanceof Function)) { - const typeName = typeof (evalFunc); + const typeName = typeof evalFunc; throw new Error(`Wrong parameter type "${typeName}' in function "set_evaluator". It supposed to be a function and it's the entrance function of your metacircular evaulator.`); } INSTANCE.evalFunction = evalFunc; @@ -72,9 +72,13 @@ export function set_evaluator(evalFunc: Function) { * @param {content} the content you want to display * @category Main */ -export function repl_display(content: any) : any { +export function repl_display(content: any): any { if (INSTANCE.richDisplayInternal(content) === 'not_rich_text_pair') { - INSTANCE.pushOutputString(content.toString(), COLOR_REPL_DISPLAY_DEFAULT, 'plaintext');// students may set the value of the parameter "str" to types other than a string (for example "repl_display(1)" ). So here I need to first convert the parameter "str" into a string before preceding. + INSTANCE.pushOutputString( + content.toString(), + COLOR_REPL_DISPLAY_DEFAULT, + 'plaintext' + ); // students may set the value of the parameter "str" to types other than a string (for example "repl_display(1)" ). So here I need to first convert the parameter "str" into a string before preceding. return content; } return undefined; @@ -87,7 +91,7 @@ export function repl_display(content: any) : any { * * @category Main */ -export function set_background_image(img_url: string, background_color_alpha: number) : void { +export function set_background_image(img_url: string, background_color_alpha: number): void { INSTANCE.customizedEditorProps.backgroundImageUrl = img_url; INSTANCE.customizedEditorProps.backgroundColorAlpha = background_color_alpha; } @@ -109,7 +113,7 @@ export function set_font_size(font_size_px: number) { * * @category Main */ -export function default_js_slang(_program: string) : any { +export function default_js_slang(_program: string): any { throw new Error('Invaild Call: Function "default_js_slang" can not be directly called by user\'s code in editor. You should use it as the parameter of the function "set_evaluator"'); // When the function is normally called by set_evaluator function, safeKey is set to "document.body", which has a type "Element". // Students can not create objects and use HTML Elements in Source due to limitations and rules in Source, so they can't set the safeKey to a HTML Element, thus they can't use this function in Source. diff --git a/src/bundles/repl/index.ts b/src/bundles/repl/index.ts index 124c276940..dd75868699 100644 --- a/src/bundles/repl/index.ts +++ b/src/bundles/repl/index.ts @@ -35,7 +35,7 @@ * * @module repl * @author Wang Zihan -*/ + */ export { set_evaluator, diff --git a/src/bundles/repl/programmable_repl.ts b/src/bundles/repl/programmable_repl.ts index bcfa686499..7be62596e4 100644 --- a/src/bundles/repl/programmable_repl.ts +++ b/src/bundles/repl/programmable_repl.ts @@ -17,7 +17,7 @@ export class ProgrammableRepl { private _tabReactComponent: any; // I store editorHeight value separately in here although it is already stored in the module's Tab React component state because I need to keep the editor height // when the Tab component is re-mounted due to the user drags the area between the module's Tab and Source Academy's original REPL to resize the module's Tab height. - public editorHeight : number; + public editorHeight: number; public customizedEditorProps = { backgroundImageUrl: 'no-background-image', @@ -26,10 +26,10 @@ export class ProgrammableRepl { }; constructor() { - this.evalFunction = (_placeholder) => this.easterEggFunction(); + this.evalFunction = _placeholder => this.easterEggFunction(); this.userCodeInEditor = this.getSavedEditorContent(); this.outputStrings = []; - this._editorInstance = null;// To be set when calling "SetEditorInstance" in the ProgrammableRepl Tab React Component render function. + this._editorInstance = null; // To be set when calling "SetEditorInstance" in the ProgrammableRepl Tab React Component render function. this.editorHeight = DEFAULT_EDITOR_HEIGHT; developmentLog(this); } @@ -50,15 +50,21 @@ export class ProgrammableRepl { } catch (exception: any) { developmentLog(exception); // If the exception has a start line of -1 and an undefined error property, then this exception is most likely to be "incorrect number of arguments" caused by incorrect number of parameters in the evaluator entry function provided by students with set_evaluator. - if (exception.location.start.line === -1 && exception.error === undefined) { - this.pushOutputString('Error: Unable to use your evaluator to run the code. Does your evaluator entry function contain and only contain exactly one parameter?', COLOR_ERROR_MESSAGE); + if ( + exception.location.start.line === -1 + && exception.error === undefined + ) { + this.pushOutputString( + 'Error: Unable to use your evaluator to run the code. Does your evaluator entry function contain and only contain exactly one parameter?', + COLOR_ERROR_MESSAGE + ); } else { this.pushOutputString(`Line ${exception.location.start.line.toString()}: ${exception.error?.message}`, COLOR_ERROR_MESSAGE); } this.reRenderTab(); return; } - if (typeof (retVal) === 'string') { + if (typeof retVal === 'string') { retVal = `"${retVal}"`; } // Here must use plain text output mode because retVal contains strings from the users. @@ -72,9 +78,14 @@ export class ProgrammableRepl { } // Rich text output method allow output strings to have html tags and css styles. - pushOutputString(content : string, textColor : string, outputMethod : string = 'plaintext') { + pushOutputString(content: string, textColor: string, outputMethod: string = 'plaintext') { const tmp = { - content: content === undefined ? 'undefined' : content === null ? 'null' : content, + content: + content === undefined + ? 'undefined' + : content === null + ? 'null' + : content, color: textColor, outputMethod }; @@ -84,7 +95,7 @@ export class ProgrammableRepl { setEditorInstance(instance: any) { if (instance === undefined) return; // It seems that when calling this function in gui->render->ref, the React internal calls this function for multiple times (at least two times) , and in at least one call the parameter 'instance' is set to 'undefined'. If I don't add this if statement, the program will throw a runtime error when rendering tab. this._editorInstance = instance; - this._editorInstance.on('guttermousedown', (e) => { + this._editorInstance.on('guttermousedown', e => { const breakpointLine = e.getDocumentPosition().row; developmentLog(breakpointLine); }); @@ -94,11 +105,11 @@ export class ProgrammableRepl { richDisplayInternal(pair_rich_text) { developmentLog(pair_rich_text); - const head = (pair) => pair[0]; - const tail = (pair) => pair[1]; - const is_pair = (obj) => obj instanceof Array && obj.length === 2; + const head = pair => pair[0]; + const tail = pair => pair[1]; + const is_pair = obj => obj instanceof Array && obj.length === 2; if (!is_pair(pair_rich_text)) return 'not_rich_text_pair'; - function checkColorStringValidity(htmlColor:string) { + function checkColorStringValidity(htmlColor: string) { if (htmlColor.length !== 7) return false; if (htmlColor[0] !== '#') return false; for (let i = 1; i < 7; i++) { @@ -111,7 +122,7 @@ export class ProgrammableRepl { return true; } function recursiveHelper(thisInstance, param): string { - if (typeof (param) === 'string') { + if (typeof param === 'string') { // There MUST be a safe check on users' strings, because users may insert something that can be interpreted as executable JavaScript code when outputing rich text. const safeCheckResult = thisInstance.userStringSafeCheck(param); if (safeCheckResult !== 'safe') { @@ -123,7 +134,7 @@ export class ProgrammableRepl { if (!is_pair(param)) { throw new Error(`Unexpected data type ${typeof (param)} when processing rich text. It should be a pair.`); } else { - const pairStyleToCssStyle : { [pairStyle : string] : string } = { + const pairStyleToCssStyle: { [pairStyle: string]: string } = { bold: 'font-weight:bold;', italic: 'font-style:italic;', small: 'font-size: 14px;', @@ -136,14 +147,12 @@ export class ProgrammableRepl { throw new Error(`The tail in style pair should always be a string, but got ${typeof (tail(param))}.`); } let style = ''; - if (tail(param) - .substring(0, 3) === 'clr') { + if (tail(param).substring(0, 3) === 'clr') { let prefix = ''; if (tail(param)[3] === 't') prefix = 'color:'; else if (tail(param)[3] === 'b') prefix = 'background-color:'; else throw new Error('Error when decoding rich text color data'); - const colorHex = tail(param) - .substring(4); + const colorHex = tail(param).substring(4); if (!checkColorStringValidity(colorHex)) { throw new Error(`Invalid html color string ${colorHex}. It should start with # and followed by 6 characters representing a hex number.`); } @@ -158,7 +167,7 @@ export class ProgrammableRepl { } } this.pushOutputString(` = { + const options: Partial = { originalMaxExecTime: 1000, scheduler: 'preemptive', stepLimit: 1000, @@ -190,12 +199,12 @@ export class ProgrammableRepl { }; context.prelude = 'const display=(x)=>repl_display(x);'; context.errors = []; // Here if I don't manually clear the "errors" array in context, the remaining errors from the last evaluation will stop the function "preprocessFileImports" in preprocessor.ts of js-slang thus stop the whole evaluation. - const sourceFile : Record = { + const sourceFile: Record = { '/ReplModuleUserCode.js': code }; runFilesInContext(sourceFile, '/ReplModuleUserCode.js', context, options) - .then((evalResult) => { + .then(evalResult => { if (evalResult.status === 'suspended' || evalResult.status === 'suspended-cse-eval') { throw new Error('This should not happen'); } @@ -209,8 +218,7 @@ export class ProgrammableRepl { const errorCount = errors.length; for (let i = 0; i < errorCount; i++) { const error = errors[i]; - if (error.explain() - .indexOf('Name repl_display not declared.') !== -1) { + if (error.explain().indexOf('Name repl_display not declared.') !== -1) { this.pushOutputString('[Error] It seems that you haven\'t import the function "repl_display" correctly when calling "set_evaluator" in Source Academy\'s main editor.', COLOR_ERROR_MESSAGE); } else this.pushOutputString(`Line ${error.location.start.line}: ${error.type} Error: ${error.explain()} (${error.elaborate()})`, COLOR_ERROR_MESSAGE); } @@ -221,12 +229,12 @@ export class ProgrammableRepl { return 'Async run in js-slang'; } - setTabReactComponentInstance(tab : any) { + setTabReactComponentInstance(tab: any) { this._tabReactComponent = tab; } private reRenderTab() { - this._tabReactComponent.setState({});// Forces the tab React Component to re-render using setState + this._tabReactComponent.setState({}); // Forces the tab React Component to re-render using setState } saveEditorContent() { @@ -245,7 +253,7 @@ export class ProgrammableRepl { private easterEggFunction() { this.pushOutputString('
', 'white', 'richtext'); this.pushOutputString( - 'If you see this, please check whether you have called set_evaluator function with the correct parameter before using the Programmable Repl Tab.', + "If you see this, please check whether you have called set_evaluator function with the correct parameter before using the Programmable Repl Tab.", 'yellow', 'richtext' ); diff --git a/src/bundles/robot_simulation/engine/Core/CallbackHandler.ts b/src/bundles/robot_simulation/engine/Core/CallbackHandler.ts index 76e1bae8d2..77b51c56fe 100644 --- a/src/bundles/robot_simulation/engine/Core/CallbackHandler.ts +++ b/src/bundles/robot_simulation/engine/Core/CallbackHandler.ts @@ -26,7 +26,7 @@ export class CallbackHandler { this.currentStepCount = frameTimingInfo.stepCount; - this.callbackStore = this.callbackStore.filter((callbackEntry) => { + this.callbackStore = this.callbackStore.filter(callbackEntry => { callbackEntry.delay -= frameTimingInfo.timestep; if (callbackEntry.delay <= 0) { diff --git a/src/bundles/robot_simulation/engine/Core/Controller.ts b/src/bundles/robot_simulation/engine/Core/Controller.ts index af3c50d2d7..9f1eb88ef9 100644 --- a/src/bundles/robot_simulation/engine/Core/Controller.ts +++ b/src/bundles/robot_simulation/engine/Core/Controller.ts @@ -26,7 +26,7 @@ implements Controller { await this.callbacks?.start?.(); await Promise.all( Object.values(this.map) - .map(async (controller) => { + .map(async controller => { await controller.start?.(); }), ); @@ -35,7 +35,7 @@ implements Controller { update(timingInfo: PhysicsTimingInfo): void { this.callbacks?.update?.(timingInfo); Object.values(this.map) - .forEach((controller) => { + .forEach(controller => { controller.update?.(timingInfo); }); } @@ -43,7 +43,7 @@ implements Controller { fixedUpdate(timingInfo: PhysicsTimingInfo): void { this.callbacks?.fixedUpdate?.(timingInfo); Object.values(this.map) - .forEach((controller) => { + .forEach(controller => { controller.fixedUpdate?.(timingInfo); }); } @@ -51,7 +51,7 @@ implements Controller { onDestroy(): void { this.callbacks?.onDestroy?.(); Object.values(this.map) - .forEach((controller) => { + .forEach(controller => { controller.onDestroy?.(); }); } @@ -66,26 +66,26 @@ export class ControllerGroup implements Controller { async start?(): Promise { await Promise.all( - this.controllers.map(async (controller) => { + this.controllers.map(async controller => { await controller.start?.(); }), ); } update(timingInfo: PhysicsTimingInfo): void { - this.controllers.forEach((controller) => { + this.controllers.forEach(controller => { controller.update?.(timingInfo); }); } fixedUpdate(timingInfo: PhysicsTimingInfo): void { - this.controllers.forEach((controller) => { + this.controllers.forEach(controller => { controller.fixedUpdate?.(timingInfo); }); } onDestroy(): void { - this.controllers.forEach((controller) => { + this.controllers.forEach(controller => { controller.onDestroy?.(); }); this.controllers = []; diff --git a/src/bundles/robot_simulation/engine/Core/Events.ts b/src/bundles/robot_simulation/engine/Core/Events.ts index 58402cdbd1..ae01d6102f 100644 --- a/src/bundles/robot_simulation/engine/Core/Events.ts +++ b/src/bundles/robot_simulation/engine/Core/Events.ts @@ -32,7 +32,7 @@ export class TypedEventTarget> { ): boolean { const listeners = this.listeners[_type]; if (listeners) { - listeners.forEach((listener) => { + listeners.forEach(listener => { listener(event); }); } diff --git a/src/bundles/robot_simulation/engine/Render/Renderer.ts b/src/bundles/robot_simulation/engine/Render/Renderer.ts index 2234876128..dbc7fed633 100644 --- a/src/bundles/robot_simulation/engine/Render/Renderer.ts +++ b/src/bundles/robot_simulation/engine/Render/Renderer.ts @@ -11,7 +11,7 @@ type ControlType = 'none' | 'orbit'; export type RenderConfig = { width: number; height: number; - control: ControlType + control: ControlType; }; export class Renderer { diff --git a/src/bundles/robot_simulation/engine/Render/helpers/GLTF.ts b/src/bundles/robot_simulation/engine/Render/helpers/GLTF.ts index 773068a3d2..22ba84ac24 100644 --- a/src/bundles/robot_simulation/engine/Render/helpers/GLTF.ts +++ b/src/bundles/robot_simulation/engine/Render/helpers/GLTF.ts @@ -9,7 +9,7 @@ export function loadGLTF(url: string, dimension: GLTFLoaderOptions): Promise { loader.load( url, - (data) => { + data => { const box = new THREE.Box3() .setFromObject(data.scene); const meshSize = new THREE.Vector3(); @@ -24,7 +24,7 @@ export function loadGLTF(url: string, dimension: GLTFLoaderOptions): Promise reject(error), + error => reject(error), ); }); } diff --git a/src/bundles/robot_simulation/engine/World.ts b/src/bundles/robot_simulation/engine/World.ts index 95239fcda1..8e8ddfca97 100644 --- a/src/bundles/robot_simulation/engine/World.ts +++ b/src/bundles/robot_simulation/engine/World.ts @@ -44,19 +44,19 @@ export class World extends TypedEventTarget { this.controllers.addController(...controllers); this.addEventListener('worldStart', () => { - controllers.forEach((controller) => { + controllers.forEach(controller => { controller.start?.(); }); }); - this.addEventListener('beforeRender', (e) => { - controllers.forEach((controller) => { + this.addEventListener('beforeRender', e => { + controllers.forEach(controller => { controller.update?.(e.frameTimingInfo); }); }); - this.physics.addEventListener('beforePhysicsUpdate', (e) => { - controllers.forEach((controller) => { + this.physics.addEventListener('beforePhysicsUpdate', e => { + controllers.forEach(controller => { controller.fixedUpdate?.(e.frameTimingInfo); }); }); diff --git a/src/bundles/rune/display.ts b/src/bundles/rune/display.ts index c0416cd976..2eabb95c70 100644 --- a/src/bundles/rune/display.ts +++ b/src/bundles/rune/display.ts @@ -81,7 +81,7 @@ export function animate_rune( fps: number, func: RuneAnimation ) { - const anim = new AnimatedRune(duration, fps, (n) => { + const anim = new AnimatedRune(duration, fps, n => { const rune = func(n); throwIfNotRune(animate_rune.name, rune); return new NormalRune(rune); @@ -104,7 +104,7 @@ export function animate_anaglyph( fps: number, func: RuneAnimation ) { - const anim = new AnimatedRune(duration, fps, (n) => { + const anim = new AnimatedRune(duration, fps, n => { const rune = func(n); throwIfNotRune(animate_anaglyph.name, rune); return new AnaglyphRune(rune); diff --git a/src/bundles/rune/functions.ts b/src/bundles/rune/functions.ts index 6e85f95e40..df25bc5193 100644 --- a/src/bundles/rune/functions.ts +++ b/src/bundles/rune/functions.ts @@ -30,7 +30,7 @@ import { } from './runes_webgl'; export type RuneModuleState = { - drawnRunes: (AnimatedRune | DrawnRune)[] + drawnRunes: (AnimatedRune | DrawnRune)[]; }; // ============================================================================= diff --git a/src/bundles/rune/runes_ops.ts b/src/bundles/rune/runes_ops.ts index 58fc1e3781..e64c83124d 100644 --- a/src/bundles/rune/runes_ops.ts +++ b/src/bundles/rune/runes_ops.ts @@ -7,7 +7,7 @@ import { Rune } from './rune'; // Utility Functions // ============================================================================= export function throwIfNotRune(name: string, ...runes: any) { - runes.forEach((rune) => { + runes.forEach(rune => { if (!(rune instanceof Rune)) { throw Error(`${name} expects a rune as argument.`); } @@ -338,9 +338,7 @@ export const colorPalette = [ ]; export function hexToColor(hex: string): number[] { - const result = /^#?(?[a-f\d]{2})(?[a-f\d]{2})(?[a-f\d]{2})$/iu.exec( - hex - ); + const result = /^#?(?[a-f\d]{2})(?[a-f\d]{2})(?[a-f\d]{2})$/iu.exec(hex); if (result === null || result.length < 4) { return [0, 0, 0]; } diff --git a/src/bundles/rune/ruomu_journal.md b/src/bundles/rune/ruomu_journal.md index 0a98b91efe..95e217008a 100644 --- a/src/bundles/rune/ruomu_journal.md +++ b/src/bundles/rune/ruomu_journal.md @@ -1,52 +1,69 @@ # Development journal for rune module -## Todos: -## Future directions: + +## Todos + +## Future directions + - improve efficiency by compress representation using index/programInfo/gl.TRIANGLE_FAN etc. - improve efficiency by using texture cache - improve efficiency by instance drawing, however, please keep it KISS ## Work Log + ### 25 Jul 2021 + - 2:00pm - 7:30pm : get familiar with Typescript, the project structure and webGL basics. tried to directly port Runes but failed. Propose to refactor the library to make everything clearer and coherent with the current coding style. ### 26 Jul 2021 + - 9:30am - 12:30pm : implementing and porting - 1:00pm - 7:00pm : finish porting the drawing and basic shapes ### 27 Jul 2021 + - 10:00am - 12:30pm : write API documentation and check coding standard compliance - 1:00pm - 1:30pm : check git workflow and create branches/pull request etc. ### 28 Jul 2021 + - 9:00am - 9:40am : check webgl ANGLE instance drawing, decide to postpone it, because 1. it is not KISS; 2. it may not significant improve the performance; 3. it can be implemented orthorgonally with the current implementation - 9:40am - 10:20am : implemented the color library - 10:20am - 16:40pm : implement anaglyph and hollusion animation - 16:40pm - 17:00pm : touch up the documentation and comments ### 31 Jul 2021 + - 11:00am - 13:15pm : implementing the image rune feature ### 2 Aug 2021 + - 12:00pm - 1:00pm : meeting ### 5 Aug 2021 + - 14:30pm - 15:10pm : fix bugs -### +### + - 12:30pm - 1:00pm : working on #88 ### 17 Aug 2021 + - 18:00pm - 18:30pm : working on beside_frac and stack_frac definition - 18:30pm - 19:00pm : fix the documentation of types #86 ### 18 Aug 2021 + - 21:50pm - 22:20pm : fix sail/triangle ### 19 Aug 2021 + - 21:10pm - 23:20pm : fix the anaglyph/hollusion inverted problem #93, and improves CPU consumption of animation by limiting the framerate. ### 21 Aug 2021 + - 18:00pm - 21:00pm : fix the memory leak / high memomry consumption by hollusion #95 ### 5 Sep 2021 -- 12:30 - 13:30 : fix #97 #100 \ No newline at end of file + +- 12:30 - 13:30 : fix #97 #100 diff --git a/src/bundles/rune_in_words/runes_ops.ts b/src/bundles/rune_in_words/runes_ops.ts index 51e31dac07..ccddab3a5a 100644 --- a/src/bundles/rune_in_words/runes_ops.ts +++ b/src/bundles/rune_in_words/runes_ops.ts @@ -2,7 +2,7 @@ // Utility Functions // ============================================================================= export function throwIfNotRune(name: string, ...runes: any) { - runes.forEach((rune) => { + runes.forEach(rune => { if (!(typeof rune === 'string')) { throw Error(`${name} expects a rune (string) as argument.`); } diff --git a/src/bundles/scrabble/__tests__/index.ts b/src/bundles/scrabble/__tests__/index.ts index 7d3dd7ba46..e0f20c16e6 100644 --- a/src/bundles/scrabble/__tests__/index.ts +++ b/src/bundles/scrabble/__tests__/index.ts @@ -8,31 +8,25 @@ import { // Test functions test('get the word in the scrabble_words array at index 12', () => { - expect(scrabble_words[12]) - .toBe('aardwolves'); + expect(scrabble_words[12]).toBe('aardwolves'); }); test('get the word in the scrabble_letters array at index 100000', () => { - expect(scrabble_letters[100000][0]) - .toBe('n'); + expect(scrabble_letters[100000][0]).toBe('n'); }); test('scrabble_letters matches snapshot', () => { - expect(scrabble_letters) - .toMatchSnapshot(); + expect(scrabble_letters).toMatchSnapshot(); }); test('scrabble_words matches snapshot', () => { - expect(scrabble_words) - .toMatchSnapshot(); + expect(scrabble_words).toMatchSnapshot(); }); test('scrabble_letters_tiny matches snapshot', () => { - expect(scrabble_letters_tiny) - .toMatchSnapshot(); + expect(scrabble_letters_tiny).toMatchSnapshot(); }); test('scrabble_words_tiny matches snapshot', () => { - expect(scrabble_words_tiny) - .toMatchSnapshot(); + expect(scrabble_words_tiny).toMatchSnapshot(); }); diff --git a/src/bundles/scrabble/functions.ts b/src/bundles/scrabble/functions.ts index c21be3f323..fc0a5a0d74 100644 --- a/src/bundles/scrabble/functions.ts +++ b/src/bundles/scrabble/functions.ts @@ -172840,9 +172840,9 @@ export const scrabble_words = [ * order in which the letters appear in the word. */ -export const scrabble_letters = scrabble_words.map((w) => w.split('')); +export const scrabble_letters = scrabble_words.map(w => w.split('')); // Sample every 100 words to generate "tiny" dataset export const scrabble_words_tiny = scrabble_words.filter((_, i) => i % 100 === 0); -export const scrabble_letters_tiny = scrabble_words_tiny.map((w) => w.split('')); +export const scrabble_letters_tiny = scrabble_words_tiny.map(w => w.split('')); diff --git a/src/bundles/sound/__tests__/sound.test.ts b/src/bundles/sound/__tests__/sound.test.ts index b304adc133..9879bcadfd 100644 --- a/src/bundles/sound/__tests__/sound.test.ts +++ b/src/bundles/sound/__tests__/sound.test.ts @@ -13,26 +13,26 @@ describe('Test make_sound', () => { describe('Test play', () => { test('Should error gracefully when duration is negative', () => { - const sound = [(t) => 0, -1]; + const sound = [() => 0, -1]; expect(() => play(sound as any)) .toThrowErrorMatchingInlineSnapshot('"play: duration of sound is negative"'); }); test('Should not error when duration is zero', () => { - const sound = make_sound((t) => 0, 0); + const sound = make_sound(() => 0, 0); expect(() => play(sound)).not.toThrow(); }); }); describe('Test play_in_tab', () => { test('Should error gracefully when duration is negative', () => { - const sound = [(t) => 0, -1]; + const sound = [() => 0, -1]; expect(() => play_in_tab(sound as any)) .toThrowErrorMatchingInlineSnapshot('"play_in_tab: duration of sound is negative"'); }); test('Should not error when duration is zero', () => { - const sound = make_sound((t) => 0, 0); + const sound = make_sound(() => 0, 0); expect(() => play_in_tab(sound)).not.toThrow(); }); }); diff --git a/src/bundles/sound/functions.ts b/src/bundles/sound/functions.ts index 33ae8a92dd..3298439ec1 100644 --- a/src/bundles/sound/functions.ts +++ b/src/bundles/sound/functions.ts @@ -43,7 +43,7 @@ function init_audioCtx(): void { // linear decay from 1 to 0 over decay_period function linear_decay(decay_period: number): (t: number) => number { - return (t) => { + return t => { if (t > decay_period || t < 0) { return 0; } @@ -89,7 +89,7 @@ function setPermissionToFalse() { function start_recording(mediaRecorder: MediaRecorder) { const data: any[] = []; - mediaRecorder.ondataavailable = (e) => e.data.size && data.push(e.data); + mediaRecorder.ondataavailable = e => e.data.size && data.push(e.data); mediaRecorder.start(); mediaRecorder.onstop = () => process(data); } @@ -110,21 +110,20 @@ function process(data) { const blob = new Blob(data); convertToArrayBuffer(blob) - .then((arrayBuffer) => audioContext.decodeAudioData(arrayBuffer)) + .then(arrayBuffer => audioContext.decodeAudioData(arrayBuffer)) .then(save); } // Converts input microphone sound (blob) into array format. function convertToArrayBuffer(blob: Blob): Promise { const url = URL.createObjectURL(blob); - return fetch(url) - .then((response) => response.arrayBuffer()); + return fetch(url).then(response => response.arrayBuffer()); } function save(audioBuffer: AudioBuffer) { const array = audioBuffer.getChannelData(0); const duration = array.length / FS; - recorded_sound = make_sound((t) => { + recorded_sound = make_sound(t => { const index = t * FS; const lowerIndex = Math.floor(index); const upperIndex = lowerIndex + 1; @@ -468,7 +467,7 @@ export function stop(): void { * @example noise_sound(5); */ export function noise_sound(duration: number): Sound { - return make_sound((_t) => Math.random() * 2 - 1, duration); + return make_sound(_t => Math.random() * 2 - 1, duration); } /** @@ -479,7 +478,7 @@ export function noise_sound(duration: number): Sound { * @example silence_sound(5); */ export function silence_sound(duration: number): Sound { - return make_sound((_t) => 0, duration); + return make_sound(_t => 0, duration); } /** @@ -491,7 +490,7 @@ export function silence_sound(duration: number): Sound { * @example sine_sound(440, 5); */ export function sine_sound(freq: number, duration: number): Sound { - return make_sound((t) => Math.sin(2 * Math.PI * t * freq), duration); + return make_sound(t => Math.sin(2 * Math.PI * t * freq), duration); } /** @@ -510,10 +509,7 @@ export function square_sound(f: number, duration: number): Sound { } return answer; } - return make_sound( - (t) => (4 / Math.PI) * fourier_expansion_square(t), - duration - ); + return make_sound(t => (4 / Math.PI) * fourier_expansion_square(t), duration); } /** @@ -535,7 +531,7 @@ export function triangle_sound(freq: number, duration: number): Sound { return answer; } return make_sound( - (t) => (8 / Math.PI / Math.PI) * fourier_expansion_triangle(t), + t => (8 / Math.PI / Math.PI) * fourier_expansion_triangle(t), duration ); } @@ -557,7 +553,7 @@ export function sawtooth_sound(freq: number, duration: number): Sound { return answer; } return make_sound( - (t) => 1 / 2 - (1 / Math.PI) * fourier_expansion_sawtooth(t), + t => 1 / 2 - (1 / Math.PI) * fourier_expansion_sawtooth(t), duration ); } @@ -638,13 +634,13 @@ export function adsr( sustain_level: number, release_ratio: number ): SoundTransformer { - return (sound) => { + return sound => { const wave = get_wave(sound); const duration = get_duration(sound); const attack_time = duration * attack_ratio; const decay_time = duration * decay_ratio; const release_time = duration * release_ratio; - return make_sound((x) => { + return make_sound(x => { if (x < attack_time) { return wave(x) * (x / attack_time); } @@ -725,7 +721,7 @@ export function phase_mod( amount: number ): SoundTransformer { return (modulator: Sound) => make_sound( - (t) => Math.sin(2 * Math.PI * t * freq + amount * get_wave(modulator)(t)), + t => Math.sin(2 * Math.PI * t * freq + amount * get_wave(modulator)(t)), duration ); } diff --git a/src/bundles/sound/types.ts b/src/bundles/sound/types.ts index 5788c017c8..0d1ec5998e 100644 --- a/src/bundles/sound/types.ts +++ b/src/bundles/sound/types.ts @@ -14,5 +14,5 @@ export type AudioPlayed = { }; export type SoundModuleState = { - audioPlayed: AudioPlayed[] + audioPlayed: AudioPlayed[]; }; diff --git a/src/bundles/sound_matrix/functions.ts b/src/bundles/sound_matrix/functions.ts index 4198d64606..eba896c985 100644 --- a/src/bundles/sound_matrix/functions.ts +++ b/src/bundles/sound_matrix/functions.ts @@ -219,7 +219,7 @@ ToneMatrix.initialise_matrix = initialise_matrix; function bind_events_to_rect(c) { c.addEventListener( 'click', - (event) => { + event => { // calculate the x, y coordinates of the click event const rect = c.getBoundingClientRect(); const offset_top = rect.top + document.documentElement.scrollTop; diff --git a/src/bundles/stereo_sound/functions.ts b/src/bundles/stereo_sound/functions.ts index 42536c428d..8a99190bad 100644 --- a/src/bundles/stereo_sound/functions.ts +++ b/src/bundles/stereo_sound/functions.ts @@ -44,7 +44,7 @@ function init_audioCtx(): void { // linear decay from 1 to 0 over decay_period function linear_decay(decay_period: number): (t: number) => number { - return (t) => { + return t => { if (t > decay_period || t < 0) { return 0; } @@ -90,7 +90,7 @@ function setPermissionToFalse() { function start_recording(mediaRecorder: MediaRecorder) { const data: any[] = []; - mediaRecorder.ondataavailable = (e) => e.data.size && data.push(e.data); + mediaRecorder.ondataavailable = e => e.data.size && data.push(e.data); mediaRecorder.start(); mediaRecorder.onstop = () => process(data); } @@ -109,21 +109,20 @@ function process(data: any[] | undefined) { const blob = new Blob(data); convertToArrayBuffer(blob) - .then((arrayBuffer) => audioContext.decodeAudioData(arrayBuffer)) + .then(arrayBuffer => audioContext.decodeAudioData(arrayBuffer)) .then(save); } // Converts input microphone sound (blob) into array format. function convertToArrayBuffer(blob: Blob): Promise { const url = URL.createObjectURL(blob); - return fetch(url) - .then((response) => response.arrayBuffer()); + return fetch(url).then(response => response.arrayBuffer()); } function save(audioBuffer: AudioBuffer) { const array = audioBuffer.getChannelData(0); const duration = array.length / FS; - recorded_sound = make_sound((t) => { + recorded_sound = make_sound(t => { const index = t * FS; const lowerIndex = Math.floor(index); const upperIndex = lowerIndex + 1; @@ -570,7 +569,7 @@ export function stop(): void { export function squash(sound: Sound): Sound { const left = get_left_wave(sound); const right = get_right_wave(sound); - return make_sound((t) => 0.5 * (left(t) + right(t)), get_duration(sound)); + return make_sound(t => 0.5 * (left(t) + right(t)), get_duration(sound)); } /** @@ -582,7 +581,7 @@ export function squash(sound: Sound): Sound { * @return a Sound Transformer that pans a Sound */ export function pan(amount: number): SoundTransformer { - return (sound) => { + return sound => { if (amount > 1) { amount = 1; } @@ -591,8 +590,8 @@ export function pan(amount: number): SoundTransformer { } sound = squash(sound); return make_stereo_sound( - (t) => ((1 - amount) / 2) * get_left_wave(sound)(t), - (t) => ((1 + amount) / 2) * get_right_wave(sound)(t), + t => ((1 - amount) / 2) * get_left_wave(sound)(t), + t => ((1 + amount) / 2) * get_right_wave(sound)(t), get_duration(sound) ); }; @@ -618,11 +617,11 @@ export function pan_mod(modulator: Sound): SoundTransformer { } return output; }; - return (sound) => { + return sound => { sound = squash(sound); return make_stereo_sound( - (t) => ((1 - amount(t)) / 2) * get_left_wave(sound)(t), - (t) => ((1 + amount(t)) / 2) * get_right_wave(sound)(t), + t => ((1 - amount(t)) / 2) * get_left_wave(sound)(t), + t => ((1 + amount(t)) / 2) * get_right_wave(sound)(t), get_duration(sound) ); }; @@ -638,7 +637,7 @@ export function pan_mod(modulator: Sound): SoundTransformer { * @example noise_sound(5); */ export function noise_sound(duration: number): Sound { - return make_sound((_t) => Math.random() * 2 - 1, duration); + return make_sound(_t => Math.random() * 2 - 1, duration); } /** @@ -649,7 +648,7 @@ export function noise_sound(duration: number): Sound { * @example silence_sound(5); */ export function silence_sound(duration: number): Sound { - return make_sound((_t) => 0, duration); + return make_sound(_t => 0, duration); } /** @@ -661,7 +660,7 @@ export function silence_sound(duration: number): Sound { * @example sine_sound(440, 5); */ export function sine_sound(freq: number, duration: number): Sound { - return make_sound((t) => Math.sin(2 * Math.PI * t * freq), duration); + return make_sound(t => Math.sin(2 * Math.PI * t * freq), duration); } /** @@ -680,10 +679,7 @@ export function square_sound(f: number, duration: number): Sound { } return answer; } - return make_sound( - (t) => (4 / Math.PI) * fourier_expansion_square(t), - duration - ); + return make_sound(t => (4 / Math.PI) * fourier_expansion_square(t), duration); } /** @@ -705,7 +701,7 @@ export function triangle_sound(freq: number, duration: number): Sound { return answer; } return make_sound( - (t) => (8 / Math.PI / Math.PI) * fourier_expansion_triangle(t), + t => (8 / Math.PI / Math.PI) * fourier_expansion_triangle(t), duration ); } @@ -727,7 +723,7 @@ export function sawtooth_sound(freq: number, duration: number): Sound { return answer; } return make_sound( - (t) => 1 / 2 - (1 / Math.PI) * fourier_expansion_sawtooth(t), + t => 1 / 2 - (1 / Math.PI) * fourier_expansion_sawtooth(t), duration ); } @@ -817,7 +813,7 @@ export function adsr( sustain_level: number, release_ratio: number ): SoundTransformer { - return (sound) => { + return sound => { const Lwave = get_left_wave(sound); const Rwave = get_right_wave(sound); const duration = get_duration(sound); @@ -909,8 +905,8 @@ export function phase_mod( amount: number ): SoundTransformer { return (modulator: Sound) => make_stereo_sound( - (t) => Math.sin(2 * Math.PI * t * freq + amount * get_left_wave(modulator)(t)), - (t) => Math.sin( + t => Math.sin(2 * Math.PI * t * freq + amount * get_left_wave(modulator)(t)), + t => Math.sin( 2 * Math.PI * t * freq + amount * get_right_wave(modulator)(t) ), duration diff --git a/src/bundles/unity_academy/UnityAcademy.tsx b/src/bundles/unity_academy/UnityAcademy.tsx index 5b865858af..cdf4391da0 100644 --- a/src/bundles/unity_academy/UnityAcademy.tsx +++ b/src/bundles/unity_academy/UnityAcademy.tsx @@ -13,64 +13,66 @@ import { Vector3, normalizeVector, zeroVector, pointDistance } from './UnityAcad import { UNITY_ACADEMY_BACKEND_URL, BUILD_NAME } from './config'; type Transform = { - position : Vector3; - rotation : Vector3; - scale : Vector3; + position: Vector3; + rotation: Vector3; + scale: Vector3; }; type StudentGameObject = { - startMethod : Function | null; - updateMethod : Function | null; - onCollisionEnterMethod : Function | null; - onCollisionStayMethod : Function | null; - onCollisionExitMethod : Function | null; - transform : Transform; - rigidbody : RigidbodyData | null; - audioSource : AudioSourceData | null; - customProperties : any; - isDestroyed : boolean; // [set by interop] + startMethod: Function | null; + updateMethod: Function | null; + onCollisionEnterMethod: Function | null; + onCollisionStayMethod: Function | null; + onCollisionExitMethod: Function | null; + transform: Transform; + rigidbody: RigidbodyData | null; + audioSource: AudioSourceData | null; + customProperties: any; + isDestroyed: boolean; // [set by interop] }; type InputData = { - keyboardInputInfo : { [key : string] : number }; + keyboardInputInfo: { [key: string]: number }; }; type RigidbodyData = { - velocity : Vector3; - angularVelocity : Vector3; - mass : number; - useGravity : boolean; - drag : number; - angularDrag : number; + velocity: Vector3; + angularVelocity: Vector3; + mass: number; + useGravity: boolean; + drag: number; + angularDrag: number; }; type AudioSourceData = { - audioClipIdentifier : AudioClipIdentifier; - playSpeed : number; - playProgress : number; - volume : number; - isLooping : boolean; - isPlaying : boolean; + audioClipIdentifier: AudioClipIdentifier; + playSpeed: number; + playProgress: number; + volume: number; + isLooping: boolean; + isPlaying: boolean; }; -declare const createUnityInstance : Function; // This function comes from {BUILD_NAME}.loader.js in Unity Academy Application (For Example: ua-frontend-prod.loader.js) +declare const createUnityInstance: Function; // This function comes from {BUILD_NAME}.loader.js in Unity Academy Application (For Example: ua-frontend-prod.loader.js) -export function getInstance() : UnityAcademyJsInteropContext { +export function getInstance(): UnityAcademyJsInteropContext { return (window as any).unityAcademyContext as UnityAcademyJsInteropContext; } type AudioClipInternalName = string; -export class AudioClipIdentifier { // A wrapper class to store identifier string and prevent users from using arbitrary string for idenfitier - audioClipInternalName : AudioClipInternalName; - constructor(audioClipInternalName : string) { +export class AudioClipIdentifier { + // A wrapper class to store identifier string and prevent users from using arbitrary string for idenfitier + audioClipInternalName: AudioClipInternalName; + constructor(audioClipInternalName: string) { this.audioClipInternalName = audioClipInternalName; } } -export class GameObjectIdentifier { // A wrapper class to store identifier string and prevent users from using arbitrary string for idenfitier - gameObjectIdentifier : string; - constructor(gameObjectIdentifier : string) { +export class GameObjectIdentifier { + // A wrapper class to store identifier string and prevent users from using arbitrary string for idenfitier + gameObjectIdentifier: string; + constructor(gameObjectIdentifier: string) { this.gameObjectIdentifier = gameObjectIdentifier; } } @@ -88,44 +90,50 @@ class UnityComponent extends React.Component { render() { const moduleInstance = getInstance(); return ( - //
-
-
+
-

Preparing to load Unity Academy... + left: '0%', + top: '0%', + zIndex: '9999' + }} + > +

+

+ Preparing to load Unity Academy...

- - +

The actual frame rate depends on your device's performance.

{highFPSWarning} -
-
Code Examples: Click Here
-
3D Prefab Information: Click Here{dimensionMode === '2d' && ' (You need 3D mode to use prefabs.)'}
-
-
Please note that before using Unity Academy and this module, you must agree to our User Agreement
-
- {getInstance() - .getUserAgreementStatus() === 'new_user_agreement' &&
The User Agreement has updated.
} - { - if (e !== null) { - e.checked = (getInstance() - .getUserAgreementStatus() === 'agreed'); - this.userAgreementCheckboxChecked = e.checked; - } - }} onChange={(event : React.ChangeEvent) => { - this.userAgreementCheckboxChecked = event.target.checked; - getInstance() - .setUserAgreementStatus(this.userAgreementCheckboxChecked); - }} /> +
+
+ Code Examples:{' '} + + Click Here + +
+
+ 3D Prefab Information:{' '} + + Click Here + + {dimensionMode === '2d' && ' (You need 3D mode to use prefabs.)'} +
+
+
+ Please note that before using Unity Academy and this module, you must + agree to our{' '} + + User Agreement + +
+
+ {getInstance().getUserAgreementStatus() === 'new_user_agreement' && ( +
+ The User Agreement has updated. +
+
+ )} + { + if (e !== null) { + e.checked = getInstance().getUserAgreementStatus() === 'agreed'; + this.userAgreementCheckboxChecked = e.checked; + } + }} + onChange={(event: React.ChangeEvent) => { + this.userAgreementCheckboxChecked = event.target.checked; + getInstance().setUserAgreementStatus(this.userAgreementCheckboxChecked); + }} + />
); } - openUnityWindow(resolution : number) : void { + openUnityWindow(resolution: number): void { if (!this.userAgreementCheckboxChecked) { alert('You must agree to the our User Agreement before using Unity Academy and this module!'); return; diff --git a/src/tabs/common/AnimationCanvas.tsx b/src/tabs/common/AnimationCanvas.tsx index 8ff2dbe7ae..42d332e073 100644 --- a/src/tabs/common/AnimationCanvas.tsx +++ b/src/tabs/common/AnimationCanvas.tsx @@ -159,7 +159,7 @@ export default class AnimationCanvas extends React.Component< } else { // Animation hasn't ended, so just draw the next frame this.setState( - (prev) => ({ + prev => ({ animTimestamp: prev.animTimestamp + currentFrame }), () => { @@ -182,17 +182,14 @@ export default class AnimationCanvas extends React.Component< * Reset button click handler */ private onResetButtonClick = () => { - this.setState( - { animTimestamp: 0 }, - () => { - if (this.state.isPlaying) { - // Force stop - this.onPlayButtonClick(); - } - - this.drawFrame(); + this.setState({ animTimestamp: 0 }, () => { + if (this.state.isPlaying) { + // Force stop + this.onPlayButtonClick(); } - ); + + this.drawFrame(); + }); }; /** @@ -202,7 +199,7 @@ export default class AnimationCanvas extends React.Component< private onSliderChange = (newValue: number) => { this.callbackTimestamp = null; this.setState( - (prev) => ({ + prev => ({ wasPlaying: prev.isPlaying, isPlaying: false, animTimestamp: newValue @@ -216,7 +213,7 @@ export default class AnimationCanvas extends React.Component< */ private onSliderRelease = () => { this.setState( - (prev) => ({ + prev => ({ isPlaying: prev.wasPlaying }), () => { @@ -233,115 +230,101 @@ export default class AnimationCanvas extends React.Component< * Auto loop switch onChange callback */ private onSwitchChange = () => { - this.setState((prev) => ({ + this.setState(prev => ({ isAutoLooping: !prev.isAutoLooping })); }; public render() { - return
-
-
- - +
+
- - - - - - + onClick={this.onPlayButtonClick} + /> + + + + + + + +
-
-
- {this.state.errored - ? ( -
-
+ {this.state.errored ? ( +
- -
+
+ flexDirection: 'row', + alignItems: 'center' + }} + > + +

An error occurred while running your animation!

Here's the details:

- + {this.state.errored.toString()} -
) - : ( +
+ ) : ( { + style={{ flexGrow: 1 }} + ref={r => { this.canvas = r; }} /> )} +
-
; + ); } } diff --git a/src/tabs/common/AutoLoopSwitch.tsx b/src/tabs/common/AutoLoopSwitch.tsx index 13cec03797..75cd8f92dc 100644 --- a/src/tabs/common/AutoLoopSwitch.tsx +++ b/src/tabs/common/AutoLoopSwitch.tsx @@ -3,23 +3,25 @@ import { Switch, type SwitchProps } from '@blueprintjs/core'; import React from 'react'; export type AutoLoopSwitchProps = Omit & { - isAutoLooping: boolean, + isAutoLooping: boolean; }; /* [Main] */ export default class AutoLoopSwitch extends React.Component { render() { - return ; + // Prevent label from wrapping at every letter when width is small + whiteSpace: 'nowrap' + }} + label="Auto Loop" + checked={this.props.isAutoLooping} + {...this.props} + /> + ); } } diff --git a/src/tabs/common/ButtonComponent.tsx b/src/tabs/common/ButtonComponent.tsx index 4eb3d68ab2..eb35491d69 100644 --- a/src/tabs/common/ButtonComponent.tsx +++ b/src/tabs/common/ButtonComponent.tsx @@ -10,22 +10,20 @@ const defaultOptions = { }; type Props = { - onClick?: MouseEventHandler, - disabled?: boolean, - children?: ReactNode, + onClick?: MouseEventHandler; + disabled?: boolean; + children?: ReactNode; }; -const ButtonComponent = (props: Props) => { +const ButtonComponent: React.FC = props => { const buttonProps = { ...defaultOptions, ...props }; - return props.disabled - ? ( - - ) - : ( -