diff --git a/.github/workflows/pages-deploy.yml b/.github/workflows/pages-deploy.yml index f8107dea7..3ac0ae982 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 9dc657cb0..bad059b58 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 c1655131a..f8c2f2871 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 df07be32f..9ae728d45 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 b43160729..0107c4a8f 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 840263ca9..02cac35ad 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 734d6a633..1d7e2c646 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 858f7a9f1..af18450cb 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 249cacc57..14c81360e 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 adb04e941..44ce463c1 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 f586b8744..5ee8edb2b 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 e07163fd1..a3600c013 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 3bc31c9cc..860480ab3 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 60e8b5f71..c0118b44e 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 27125198f..01acd221b 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 cc1fcd011..aa64ef6e8 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 c9108f5f3..b4891a7ce 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 c6e5529fe..f561f3089 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 770e07a92..336b2ba41 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 38c8f7044..771c8bbb5 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 4ee15bbce..c779b2987 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 914bd7bc8..b3e413979 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 93c9d5e00..4b82ee9a4 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 fc7ac69ed..a516fd5b1 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 dce466ea7..eb759e40c 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 8532cf4da..e74da0b3d 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 0adf8f5be..79538a4fd 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 8fe5d5aaa..4efeeaf67 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 8594bed41..803afbf13 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 817af3917..22a52031b 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 aab3c3e70..31595d4ac 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 eac3ba04f..0ff31fee8 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 18f7fd9a6..c58f4175b 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 934883a48..12076a0c7 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 d8c4832b8..3921bcae9 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 2e4f3669c..a8fc9e08b 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 0e7e9d310..1606e3f81 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 b0f85e11e..34084169a 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 439b153ea..79e204e6d 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 8ae4498ef..6022e1666 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 53b38a02c..52c97c2b0 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 eaf0b6ce6..f4a90b8cf 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 34eb95b09..76dd1bcfc 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 e6d93c3cf..8c5decac2 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 b6c606ee4..e1619bdae 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 897b90573..71e5118ef 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 ba41fdcdc..7e2f1ec1f 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 28c22a918..1cf943a44 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 5e52cbd24..d2242b221 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 b2d53b977..5d09af855 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 03c86b1fb..d51cf7b29 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 1d29f06a1..f2520f539 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 ff8b8cdb7..5edbff76e 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 f46034e09..3c96f4144 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 d82a6505f..2df90d28d 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 db0e9f13d..4051990ed 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 0668fbaa1..7901655bc 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 af4e6e699..5d3bc03a0 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 4fc993db1..51a8933c2 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 701d1c296..b665169ab 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 9176542d8..facd6104f 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 9df32eafd..933a2c2c9 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 4ff97dcdc..f912e7658 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 e045328cb..da8059a19 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 e5cbee63e..78379fa53 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 04132ca47..da87c17e9 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 83beb643f..9ebf42e56 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 e6efaaa6e..836afd7ed 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 353cea7e2..7943b9b86 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 42ad074af..9f95d6c4f 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 e4e553763..603df598b 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 948e3c8d1..15834e693 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 124c27694..dd7586869 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 bcfa68649..7be62596e 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 76e1bae8d..77b51c56f 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 af3c50d2d..9f1eb88ef 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 58402cdbd..ae01d6102 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 223487612..dbc7fed63 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 773068a3d..22ba84ac2 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 95239fcda..8e8ddfca9 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 c0416cd97..2eabb95c7 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 6e85f95e4..df25bc519 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 58fc1e378..e64c83124 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 0a98b91ef..95e217008 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 51e31dac0..ccddab3a5 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 7d3dd7ba4..e0f20c16e 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 c21be3f32..fc0a5a0d7 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 b304adc13..9879bcadf 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 33ae8a92d..3298439ec 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 5788c017c..0d1ec5998 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 4198d6460..eba896c98 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 42536c428..8a99190ba 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 5b865858a..cdf4391da 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 8ff2dbe7a..42d332e07 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 13cec0379..75cd8f92d 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 4eb3d68ab..eb35491d6 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 - ? ( - - ) - : ( -